ac-library-rb 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/unittest.yml +16 -0
- data/.gitignore +11 -0
- data/.rubocop.yml +198 -0
- data/Gemfile +3 -0
- data/LICENSE +116 -0
- data/README.ja.md +56 -0
- data/README.md +41 -0
- data/Rakefile +11 -0
- data/ac-library-rb.gemspec +32 -0
- data/bin/console +8 -0
- data/bin/lock_lib.rb +27 -0
- data/bin/setup +8 -0
- data/document_en/binary_index_tree.md +3 -0
- data/document_en/convolution.md +67 -0
- data/document_en/dsu.md +132 -0
- data/document_en/fenwick_tree.md +99 -0
- data/document_en/index.md +79 -0
- data/document_en/lazy_segtree.md +141 -0
- data/document_en/math.md +104 -0
- data/document_en/max_flow.md +165 -0
- data/document_en/min_cost_flow.md +132 -0
- data/document_en/modint.md +263 -0
- data/document_en/priority_queue.md +119 -0
- data/document_en/segtree.md +134 -0
- data/document_en/string.md +106 -0
- data/document_en/two_sat.md +91 -0
- data/document_en/union_find.md +3 -0
- data/document_ja/convolution.md +64 -0
- data/document_ja/dsu.md +183 -0
- data/document_ja/fenwick_tree.md +83 -0
- data/document_ja/index.md +89 -0
- data/document_ja/lazy_segtree.md +135 -0
- data/document_ja/math.md +116 -0
- data/document_ja/max_flow.md +129 -0
- data/document_ja/min_cost_flow.md +105 -0
- data/document_ja/modint.md +349 -0
- data/document_ja/priority_queue.md +103 -0
- data/document_ja/scc.md +65 -0
- data/document_ja/segtree.md +145 -0
- data/document_ja/string.md +105 -0
- data/document_ja/two_sat.md +87 -0
- data/lib/ac-library-rb/version.rb +3 -0
- data/lib/convolution.rb +124 -0
- data/lib/core_ext/modint.rb +19 -0
- data/lib/crt.rb +52 -0
- data/lib/dsu.rb +44 -0
- data/lib/fenwick_tree.rb +48 -0
- data/lib/floor_sum.rb +21 -0
- data/lib/inv_mod.rb +26 -0
- data/lib/lazy_segtree.rb +149 -0
- data/lib/lcp_array.rb +23 -0
- data/lib/max_flow.rb +137 -0
- data/lib/min_cost_flow.rb +143 -0
- data/lib/modint.rb +170 -0
- data/lib/pow_mod.rb +13 -0
- data/lib/priority_queue.rb +89 -0
- data/lib/scc.rb +77 -0
- data/lib/segtree.rb +140 -0
- data/lib/suffix_array.rb +128 -0
- data/lib/two_sat.rb +34 -0
- data/lib/z_algorithm.rb +32 -0
- data/lib_helpers/ac-library-rb/all.rb +22 -0
- data/lib_lock/ac-library-rb.rb +22 -0
- data/lib_lock/ac-library-rb/convolution.rb +126 -0
- data/lib_lock/ac-library-rb/core_ext/modint.rb +19 -0
- data/lib_lock/ac-library-rb/crt.rb +54 -0
- data/lib_lock/ac-library-rb/dsu.rb +46 -0
- data/lib_lock/ac-library-rb/fenwick_tree.rb +50 -0
- data/lib_lock/ac-library-rb/floor_sum.rb +23 -0
- data/lib_lock/ac-library-rb/inv_mod.rb +28 -0
- data/lib_lock/ac-library-rb/lazy_segtree.rb +151 -0
- data/lib_lock/ac-library-rb/lcp_array.rb +25 -0
- data/lib_lock/ac-library-rb/max_flow.rb +139 -0
- data/lib_lock/ac-library-rb/min_cost_flow.rb +145 -0
- data/lib_lock/ac-library-rb/modint.rb +172 -0
- data/lib_lock/ac-library-rb/pow_mod.rb +15 -0
- data/lib_lock/ac-library-rb/priority_queue.rb +91 -0
- data/lib_lock/ac-library-rb/scc.rb +79 -0
- data/lib_lock/ac-library-rb/segtree.rb +142 -0
- data/lib_lock/ac-library-rb/suffix_array.rb +130 -0
- data/lib_lock/ac-library-rb/two_sat.rb +36 -0
- data/lib_lock/ac-library-rb/z_algorithm.rb +34 -0
- metadata +158 -0
data/lib/two_sat.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require_relative './scc.rb'
|
2
|
+
|
3
|
+
# TwoSAT
|
4
|
+
# Reference: https://github.com/atcoder/ac-library/blob/master/atcoder/twosat.hpp
|
5
|
+
class TwoSAT
|
6
|
+
def initialize(n = 0)
|
7
|
+
@n = n
|
8
|
+
@answer = Array.new(n)
|
9
|
+
@scc = SCCGraph.new(2 * n)
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :answer
|
13
|
+
|
14
|
+
def add_clause(i, f, j, g)
|
15
|
+
raise RangeError unless (0...@n).cover?(i) && (0...@n).cover?(j)
|
16
|
+
|
17
|
+
@scc.add_edge(2 * i + (f ? 0 : 1), 2 * j + (g ? 1 : 0))
|
18
|
+
@scc.add_edge(2 * j + (g ? 0 : 1), 2 * i + (f ? 1 : 0))
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def satisfiable
|
23
|
+
id = @scc.send(:scc_ids)[1]
|
24
|
+
@n.times do |i|
|
25
|
+
return false if id[2 * i] == id[2 * i + 1]
|
26
|
+
|
27
|
+
@answer[i] = id[2 * i] < id[2 * i + 1]
|
28
|
+
end
|
29
|
+
true
|
30
|
+
end
|
31
|
+
alias satisfiable? satisfiable
|
32
|
+
end
|
33
|
+
|
34
|
+
TwoSat = TwoSAT
|
data/lib/z_algorithm.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# this implementation is different from ACL because of calculation time
|
2
|
+
# ref : https://snuke.hatenablog.com/entry/2014/12/03/214243
|
3
|
+
# ACL implementation : https://atcoder.jp/contests/abc135/submissions/18836384 (731ms)
|
4
|
+
# this implementation : https://atcoder.jp/contests/abc135/submissions/18836378 (525ms)
|
5
|
+
|
6
|
+
def z_algorithm(s)
|
7
|
+
n = s.size
|
8
|
+
return [] if n == 0
|
9
|
+
|
10
|
+
s = s.codepoints if s.is_a?(String)
|
11
|
+
|
12
|
+
z = [0] * n
|
13
|
+
z[0] = n
|
14
|
+
i, j = 1, 0
|
15
|
+
while i < n
|
16
|
+
j += 1 while i + j < n && s[j] == s[i + j]
|
17
|
+
z[i] = j
|
18
|
+
if j == 0
|
19
|
+
i += 1
|
20
|
+
next
|
21
|
+
end
|
22
|
+
k = 1
|
23
|
+
while i + k < n && k + z[k] < j
|
24
|
+
z[i + k] = z[k]
|
25
|
+
k += 1
|
26
|
+
end
|
27
|
+
i += k
|
28
|
+
j -= k
|
29
|
+
end
|
30
|
+
|
31
|
+
return z
|
32
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require_relative "../../lib_lock/ac-library-rb/convolution"
|
2
|
+
require_relative "../../lib_lock/ac-library-rb/crt"
|
3
|
+
require_relative "../../lib_lock/ac-library-rb/dsu"
|
4
|
+
require_relative "../../lib_lock/ac-library-rb/fenwick_tree"
|
5
|
+
require_relative "../../lib_lock/ac-library-rb/floor_sum"
|
6
|
+
require_relative "../../lib_lock/ac-library-rb/inv_mod"
|
7
|
+
require_relative "../../lib_lock/ac-library-rb/lazy_segtree"
|
8
|
+
require_relative "../../lib_lock/ac-library-rb/lcp_array"
|
9
|
+
require_relative "../../lib_lock/ac-library-rb/max_flow"
|
10
|
+
require_relative "../../lib_lock/ac-library-rb/min_cost_flow"
|
11
|
+
require_relative "../../lib_lock/ac-library-rb/modint"
|
12
|
+
require_relative "../../lib_lock/ac-library-rb/pow_mod"
|
13
|
+
require_relative "../../lib_lock/ac-library-rb/priority_queue"
|
14
|
+
require_relative "../../lib_lock/ac-library-rb/scc"
|
15
|
+
require_relative "../../lib_lock/ac-library-rb/segtree"
|
16
|
+
require_relative "../../lib_lock/ac-library-rb/suffix_array"
|
17
|
+
require_relative "../../lib_lock/ac-library-rb/two_sat"
|
18
|
+
require_relative "../../lib_lock/ac-library-rb/z_algorithm"
|
19
|
+
|
20
|
+
# Usage:
|
21
|
+
# require 'ac-library-rb/all'
|
22
|
+
# include AcLibraryRb
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module AcLibraryRb
|
2
|
+
end
|
3
|
+
include AcLibraryRb
|
4
|
+
|
5
|
+
require_relative './ac-library-rb/convolution'
|
6
|
+
require_relative './ac-library-rb/crt'
|
7
|
+
require_relative './ac-library-rb/dsu'
|
8
|
+
require_relative './ac-library-rb/fenwick_tree'
|
9
|
+
require_relative './ac-library-rb/floor_sum'
|
10
|
+
require_relative './ac-library-rb/inv_mod'
|
11
|
+
require_relative './ac-library-rb/lazy_segtree'
|
12
|
+
require_relative './ac-library-rb/lcp_array'
|
13
|
+
require_relative './ac-library-rb/max_flow'
|
14
|
+
require_relative './ac-library-rb/min_cost_flow'
|
15
|
+
require_relative './ac-library-rb/modint'
|
16
|
+
require_relative './ac-library-rb/pow_mod'
|
17
|
+
require_relative './ac-library-rb/priority_queue'
|
18
|
+
require_relative './ac-library-rb/scc'
|
19
|
+
require_relative './ac-library-rb/segtree'
|
20
|
+
require_relative './ac-library-rb/suffix_array'
|
21
|
+
require_relative './ac-library-rb/two_sat'
|
22
|
+
require_relative './ac-library-rb/z_algorithm'
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module AcLibraryRb
|
2
|
+
# usage :
|
3
|
+
#
|
4
|
+
# conv = Convolution.new(mod, [primitive_root])
|
5
|
+
# conv.convolution(a, b) #=> convolution a and b modulo mod.
|
6
|
+
#
|
7
|
+
class Convolution
|
8
|
+
def initialize(mod = 998_244_353, primitive_root = nil)
|
9
|
+
@mod = mod
|
10
|
+
|
11
|
+
cnt2 = bsf(@mod - 1)
|
12
|
+
e = (primitive_root || calc_primitive_root(mod)).pow((@mod - 1) >> cnt2, @mod)
|
13
|
+
ie = e.pow(@mod - 2, @mod)
|
14
|
+
|
15
|
+
es = [0] * (cnt2 - 1)
|
16
|
+
ies = [0] * (cnt2 - 1)
|
17
|
+
cnt2.downto(2){ |i|
|
18
|
+
es[i - 2] = e
|
19
|
+
ies[i - 2] = ie
|
20
|
+
e = e * e % @mod
|
21
|
+
ie = ie * ie % @mod
|
22
|
+
}
|
23
|
+
now = inow = 1
|
24
|
+
|
25
|
+
@sum_e = [0] * cnt2
|
26
|
+
@sum_ie = [0] * cnt2
|
27
|
+
(cnt2 - 1).times{ |i|
|
28
|
+
@sum_e[i] = es[i] * now % @mod
|
29
|
+
now = now * ies[i] % @mod
|
30
|
+
@sum_ie[i] = ies[i] * inow % @mod
|
31
|
+
inow = inow * es[i] % @mod
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def convolution(a, b)
|
36
|
+
n = a.size
|
37
|
+
m = b.size
|
38
|
+
return [] if n == 0 || m == 0
|
39
|
+
|
40
|
+
h = (n + m - 2).bit_length
|
41
|
+
raise ArgumentError if h > @sum_e.size
|
42
|
+
|
43
|
+
z = 1 << h
|
44
|
+
|
45
|
+
a = a + [0] * (z - n)
|
46
|
+
b = b + [0] * (z - m)
|
47
|
+
|
48
|
+
batterfly(a, h)
|
49
|
+
batterfly(b, h)
|
50
|
+
|
51
|
+
c = a.zip(b).map{ |a, b| a * b % @mod }
|
52
|
+
|
53
|
+
batterfly_inv(c, h)
|
54
|
+
|
55
|
+
iz = z.pow(@mod - 2, @mod)
|
56
|
+
return c[0, n + m - 1].map{ |c| c * iz % @mod }
|
57
|
+
end
|
58
|
+
|
59
|
+
def batterfly(a, h)
|
60
|
+
1.upto(h){ |ph|
|
61
|
+
w = 1 << (ph - 1)
|
62
|
+
p = 1 << (h - ph)
|
63
|
+
now = 1
|
64
|
+
w.times{ |s|
|
65
|
+
offset = s << (h - ph + 1)
|
66
|
+
offset.upto(offset + p - 1){ |i|
|
67
|
+
l = a[i]
|
68
|
+
r = a[i + p] * now % @mod
|
69
|
+
a[i] = l + r
|
70
|
+
a[i + p] = l - r
|
71
|
+
}
|
72
|
+
now = now * @sum_e[bsf(~s)] % @mod
|
73
|
+
}
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
def batterfly_inv(a, h)
|
78
|
+
h.downto(1){ |ph|
|
79
|
+
w = 1 << (ph - 1)
|
80
|
+
p = 1 << (h - ph)
|
81
|
+
inow = 1
|
82
|
+
w.times{ |s|
|
83
|
+
offset = s << (h - ph + 1)
|
84
|
+
offset.upto(offset + p - 1){ |i|
|
85
|
+
l = a[i]
|
86
|
+
r = a[i + p]
|
87
|
+
a[i] = l + r
|
88
|
+
a[i + p] = (l - r) * inow % @mod
|
89
|
+
}
|
90
|
+
inow = inow * @sum_ie[bsf(~s)] % @mod
|
91
|
+
}
|
92
|
+
}
|
93
|
+
end
|
94
|
+
|
95
|
+
def bsf(x)
|
96
|
+
(x & -x).bit_length - 1
|
97
|
+
end
|
98
|
+
|
99
|
+
def calc_primitive_root(mod)
|
100
|
+
return 1 if mod == 2
|
101
|
+
return 3 if mod == 998_244_353
|
102
|
+
|
103
|
+
divs = [2]
|
104
|
+
x = (mod - 1) / 2
|
105
|
+
x /= 2 while x.even?
|
106
|
+
i = 3
|
107
|
+
while i * i <= x
|
108
|
+
if x % i == 0
|
109
|
+
divs << i
|
110
|
+
x /= i while x % i == 0
|
111
|
+
end
|
112
|
+
i += 2
|
113
|
+
end
|
114
|
+
divs << x if x > 1
|
115
|
+
|
116
|
+
g = 2
|
117
|
+
loop{
|
118
|
+
return g if divs.none?{ |d| g.pow((mod - 1) / d, mod) == 1 }
|
119
|
+
|
120
|
+
g += 1
|
121
|
+
}
|
122
|
+
end
|
123
|
+
|
124
|
+
private :batterfly, :batterfly_inv, :bsf, :calc_primitive_root
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
def ModInt(val)
|
2
|
+
ModInt.new(val)
|
3
|
+
end
|
4
|
+
|
5
|
+
# Integer
|
6
|
+
class Integer
|
7
|
+
def to_modint
|
8
|
+
ModInt.new(self)
|
9
|
+
end
|
10
|
+
alias to_m to_modint
|
11
|
+
end
|
12
|
+
|
13
|
+
# String
|
14
|
+
class String
|
15
|
+
def to_modint
|
16
|
+
ModInt.new(to_i)
|
17
|
+
end
|
18
|
+
alias to_m to_modint
|
19
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module AcLibraryRb
|
2
|
+
# return [rem, mod] or [0, 0] (if no solution)
|
3
|
+
def crt(r, m)
|
4
|
+
raise ArgumentError if r.size != m.size
|
5
|
+
|
6
|
+
n = r.size
|
7
|
+
r0, m0 = 0, 1
|
8
|
+
n.times do |i|
|
9
|
+
raise ArgumentError if m[i] < 1
|
10
|
+
|
11
|
+
r1, m1 = r[i] % m[i], m[i]
|
12
|
+
if m0 < m1
|
13
|
+
r0, r1 = r1, r0
|
14
|
+
m0, m1 = m1, m0
|
15
|
+
end
|
16
|
+
|
17
|
+
if m0 % m1 == 0
|
18
|
+
return [0, 0] if r0 % m1 != r1
|
19
|
+
|
20
|
+
next
|
21
|
+
end
|
22
|
+
|
23
|
+
g, im = inv_gcd(m0, m1)
|
24
|
+
u1 = m1 / g
|
25
|
+
return [0, 0] if (r1 - r0) % g != 0
|
26
|
+
|
27
|
+
x = (r1 - r0) / g * im % u1
|
28
|
+
r0 += x * m0
|
29
|
+
m0 *= u1
|
30
|
+
r0 += m0 if r0 < 0
|
31
|
+
end
|
32
|
+
|
33
|
+
return [r0, m0]
|
34
|
+
end
|
35
|
+
|
36
|
+
# internal method
|
37
|
+
# return [g, x] s.t. g = gcd(a, b), x*a = g (mod b), 0 <= x < b/g
|
38
|
+
def inv_gcd(a, b)
|
39
|
+
a %= b
|
40
|
+
return [b, 0] if a == 0
|
41
|
+
|
42
|
+
s, t = b, a
|
43
|
+
m0, m1 = 0, 1
|
44
|
+
while t > 0
|
45
|
+
u, s = s.divmod(t)
|
46
|
+
m0 -= m1 * u
|
47
|
+
s, t = t, s
|
48
|
+
m0, m1 = m1, m0
|
49
|
+
end
|
50
|
+
m0 += b / s if m0 < 0
|
51
|
+
|
52
|
+
return [s, m0]
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module AcLibraryRb
|
2
|
+
# Disjoint Set Union
|
3
|
+
class DSU
|
4
|
+
def initialize(n = 0)
|
5
|
+
# root node: -1 * component size
|
6
|
+
# otherwise: parent
|
7
|
+
@parent_or_size = Array.new(n, -1)
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_accessor :parent_or_size
|
11
|
+
|
12
|
+
def merge(a, b)
|
13
|
+
x = leader(a)
|
14
|
+
y = leader(b)
|
15
|
+
return x if x == y
|
16
|
+
|
17
|
+
x, y = y, x if -@parent_or_size[x] < -@parent_or_size[y]
|
18
|
+
@parent_or_size[x] += @parent_or_size[y]
|
19
|
+
@parent_or_size[y] = x
|
20
|
+
end
|
21
|
+
alias unite merge
|
22
|
+
|
23
|
+
def same(a, b)
|
24
|
+
leader(a) == leader(b)
|
25
|
+
end
|
26
|
+
alias same? same
|
27
|
+
|
28
|
+
def leader(a)
|
29
|
+
@parent_or_size[a] < 0 ? a : (@parent_or_size[a] = leader(@parent_or_size[a]))
|
30
|
+
end
|
31
|
+
alias root leader
|
32
|
+
alias find leader
|
33
|
+
|
34
|
+
def size(a)
|
35
|
+
-@parent_or_size[leader(a)]
|
36
|
+
end
|
37
|
+
|
38
|
+
def groups
|
39
|
+
(0 ... @parent_or_size.size).group_by{ |i| leader(i) }.values
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
UnionFind = DSU
|
44
|
+
UnionFindTree = DSU
|
45
|
+
DisjointSetUnion = DSU
|
46
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module AcLibraryRb
|
2
|
+
# Fenwick Tree
|
3
|
+
class FenwickTree
|
4
|
+
attr_reader :data, :size
|
5
|
+
|
6
|
+
def initialize(arg = 0)
|
7
|
+
case arg
|
8
|
+
when Array
|
9
|
+
@size = arg.size
|
10
|
+
@data = [0].concat(arg)
|
11
|
+
(1 ... @size).each do |i|
|
12
|
+
up = i + (i & -i)
|
13
|
+
next if up > @size
|
14
|
+
|
15
|
+
@data[up] += @data[i]
|
16
|
+
end
|
17
|
+
when Integer
|
18
|
+
@size = arg
|
19
|
+
@data = Array.new(@size + 1, 0)
|
20
|
+
else
|
21
|
+
raise ArgumentError
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def add(i, x)
|
26
|
+
i += 1
|
27
|
+
while i <= @size
|
28
|
+
@data[i] += x
|
29
|
+
i += (i & -i)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def sum(l, r)
|
34
|
+
_sum(r) - _sum(l)
|
35
|
+
end
|
36
|
+
|
37
|
+
def _sum(i)
|
38
|
+
res = 0
|
39
|
+
while i > 0
|
40
|
+
res += @data[i]
|
41
|
+
i &= i - 1
|
42
|
+
end
|
43
|
+
res
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
FeTree = FenwickTree
|
48
|
+
Fetree = FenwickTree
|
49
|
+
BinaryIndexedTree = FenwickTree
|
50
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module AcLibraryRb
|
2
|
+
def floor_sum(n, m, a, b)
|
3
|
+
res = 0
|
4
|
+
|
5
|
+
if a >= m
|
6
|
+
res += (n - 1) * n * (a / m) / 2
|
7
|
+
a %= m
|
8
|
+
end
|
9
|
+
|
10
|
+
if b >= m
|
11
|
+
res += n * (b / m)
|
12
|
+
b %= m
|
13
|
+
end
|
14
|
+
|
15
|
+
y_max = (a * n + b) / m
|
16
|
+
|
17
|
+
return res if y_max == 0
|
18
|
+
|
19
|
+
x_max = (m * y_max - b + a - 1) / a
|
20
|
+
res += (n - x_max) * y_max + floor_sum(y_max, a, m, a * x_max - m * y_max + b)
|
21
|
+
res
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module AcLibraryRb
|
2
|
+
# Use `x.pow(m - 2, m)` instead of `inv_mod(x, m)` if m is a prime number.
|
3
|
+
def inv_mod(x, m)
|
4
|
+
z = _inv_gcd(x, m)
|
5
|
+
raise ArgumentError unless z.first == 1
|
6
|
+
|
7
|
+
z[1]
|
8
|
+
end
|
9
|
+
|
10
|
+
def _inv_gcd(a, b)
|
11
|
+
a %= b # safe_mod
|
12
|
+
|
13
|
+
s, t = b, a
|
14
|
+
m0, m1 = 0, 1
|
15
|
+
|
16
|
+
while t > 0
|
17
|
+
u = s / t
|
18
|
+
s -= t * u
|
19
|
+
m0 -= m1 * u
|
20
|
+
|
21
|
+
s, t = t, s
|
22
|
+
m0, m1 = m1, m0
|
23
|
+
end
|
24
|
+
|
25
|
+
m0 += b / s if m0 < 0
|
26
|
+
[s, m0]
|
27
|
+
end
|
28
|
+
end
|