ac-library-rb 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/unittest.yml +16 -0
  3. data/.gitignore +11 -0
  4. data/.rubocop.yml +198 -0
  5. data/Gemfile +3 -0
  6. data/LICENSE +116 -0
  7. data/README.ja.md +56 -0
  8. data/README.md +41 -0
  9. data/Rakefile +11 -0
  10. data/ac-library-rb.gemspec +32 -0
  11. data/bin/console +8 -0
  12. data/bin/lock_lib.rb +27 -0
  13. data/bin/setup +8 -0
  14. data/document_en/binary_index_tree.md +3 -0
  15. data/document_en/convolution.md +67 -0
  16. data/document_en/dsu.md +132 -0
  17. data/document_en/fenwick_tree.md +99 -0
  18. data/document_en/index.md +79 -0
  19. data/document_en/lazy_segtree.md +141 -0
  20. data/document_en/math.md +104 -0
  21. data/document_en/max_flow.md +165 -0
  22. data/document_en/min_cost_flow.md +132 -0
  23. data/document_en/modint.md +263 -0
  24. data/document_en/priority_queue.md +119 -0
  25. data/document_en/segtree.md +134 -0
  26. data/document_en/string.md +106 -0
  27. data/document_en/two_sat.md +91 -0
  28. data/document_en/union_find.md +3 -0
  29. data/document_ja/convolution.md +64 -0
  30. data/document_ja/dsu.md +183 -0
  31. data/document_ja/fenwick_tree.md +83 -0
  32. data/document_ja/index.md +89 -0
  33. data/document_ja/lazy_segtree.md +135 -0
  34. data/document_ja/math.md +116 -0
  35. data/document_ja/max_flow.md +129 -0
  36. data/document_ja/min_cost_flow.md +105 -0
  37. data/document_ja/modint.md +349 -0
  38. data/document_ja/priority_queue.md +103 -0
  39. data/document_ja/scc.md +65 -0
  40. data/document_ja/segtree.md +145 -0
  41. data/document_ja/string.md +105 -0
  42. data/document_ja/two_sat.md +87 -0
  43. data/lib/ac-library-rb/version.rb +3 -0
  44. data/lib/convolution.rb +124 -0
  45. data/lib/core_ext/modint.rb +19 -0
  46. data/lib/crt.rb +52 -0
  47. data/lib/dsu.rb +44 -0
  48. data/lib/fenwick_tree.rb +48 -0
  49. data/lib/floor_sum.rb +21 -0
  50. data/lib/inv_mod.rb +26 -0
  51. data/lib/lazy_segtree.rb +149 -0
  52. data/lib/lcp_array.rb +23 -0
  53. data/lib/max_flow.rb +137 -0
  54. data/lib/min_cost_flow.rb +143 -0
  55. data/lib/modint.rb +170 -0
  56. data/lib/pow_mod.rb +13 -0
  57. data/lib/priority_queue.rb +89 -0
  58. data/lib/scc.rb +77 -0
  59. data/lib/segtree.rb +140 -0
  60. data/lib/suffix_array.rb +128 -0
  61. data/lib/two_sat.rb +34 -0
  62. data/lib/z_algorithm.rb +32 -0
  63. data/lib_helpers/ac-library-rb/all.rb +22 -0
  64. data/lib_lock/ac-library-rb.rb +22 -0
  65. data/lib_lock/ac-library-rb/convolution.rb +126 -0
  66. data/lib_lock/ac-library-rb/core_ext/modint.rb +19 -0
  67. data/lib_lock/ac-library-rb/crt.rb +54 -0
  68. data/lib_lock/ac-library-rb/dsu.rb +46 -0
  69. data/lib_lock/ac-library-rb/fenwick_tree.rb +50 -0
  70. data/lib_lock/ac-library-rb/floor_sum.rb +23 -0
  71. data/lib_lock/ac-library-rb/inv_mod.rb +28 -0
  72. data/lib_lock/ac-library-rb/lazy_segtree.rb +151 -0
  73. data/lib_lock/ac-library-rb/lcp_array.rb +25 -0
  74. data/lib_lock/ac-library-rb/max_flow.rb +139 -0
  75. data/lib_lock/ac-library-rb/min_cost_flow.rb +145 -0
  76. data/lib_lock/ac-library-rb/modint.rb +172 -0
  77. data/lib_lock/ac-library-rb/pow_mod.rb +15 -0
  78. data/lib_lock/ac-library-rb/priority_queue.rb +91 -0
  79. data/lib_lock/ac-library-rb/scc.rb +79 -0
  80. data/lib_lock/ac-library-rb/segtree.rb +142 -0
  81. data/lib_lock/ac-library-rb/suffix_array.rb +130 -0
  82. data/lib_lock/ac-library-rb/two_sat.rb +36 -0
  83. data/lib_lock/ac-library-rb/z_algorithm.rb +34 -0
  84. metadata +158 -0
@@ -0,0 +1,3 @@
1
+ module AcLibraryRb
2
+ VERSION = "0.5.0".freeze
3
+ end
@@ -0,0 +1,124 @@
1
+ # usage :
2
+ #
3
+ # conv = Convolution.new(mod, [primitive_root])
4
+ # conv.convolution(a, b) #=> convolution a and b modulo mod.
5
+ #
6
+ class Convolution
7
+ def initialize(mod = 998_244_353, primitive_root = nil)
8
+ @mod = mod
9
+
10
+ cnt2 = bsf(@mod - 1)
11
+ e = (primitive_root || calc_primitive_root(mod)).pow((@mod - 1) >> cnt2, @mod)
12
+ ie = e.pow(@mod - 2, @mod)
13
+
14
+ es = [0] * (cnt2 - 1)
15
+ ies = [0] * (cnt2 - 1)
16
+ cnt2.downto(2){ |i|
17
+ es[i - 2] = e
18
+ ies[i - 2] = ie
19
+ e = e * e % @mod
20
+ ie = ie * ie % @mod
21
+ }
22
+ now = inow = 1
23
+
24
+ @sum_e = [0] * cnt2
25
+ @sum_ie = [0] * cnt2
26
+ (cnt2 - 1).times{ |i|
27
+ @sum_e[i] = es[i] * now % @mod
28
+ now = now * ies[i] % @mod
29
+ @sum_ie[i] = ies[i] * inow % @mod
30
+ inow = inow * es[i] % @mod
31
+ }
32
+ end
33
+
34
+ def convolution(a, b)
35
+ n = a.size
36
+ m = b.size
37
+ return [] if n == 0 || m == 0
38
+
39
+ h = (n + m - 2).bit_length
40
+ raise ArgumentError if h > @sum_e.size
41
+
42
+ z = 1 << h
43
+
44
+ a = a + [0] * (z - n)
45
+ b = b + [0] * (z - m)
46
+
47
+ batterfly(a, h)
48
+ batterfly(b, h)
49
+
50
+ c = a.zip(b).map{ |a, b| a * b % @mod }
51
+
52
+ batterfly_inv(c, h)
53
+
54
+ iz = z.pow(@mod - 2, @mod)
55
+ return c[0, n + m - 1].map{ |c| c * iz % @mod }
56
+ end
57
+
58
+ def batterfly(a, h)
59
+ 1.upto(h){ |ph|
60
+ w = 1 << (ph - 1)
61
+ p = 1 << (h - ph)
62
+ now = 1
63
+ w.times{ |s|
64
+ offset = s << (h - ph + 1)
65
+ offset.upto(offset + p - 1){ |i|
66
+ l = a[i]
67
+ r = a[i + p] * now % @mod
68
+ a[i] = l + r
69
+ a[i + p] = l - r
70
+ }
71
+ now = now * @sum_e[bsf(~s)] % @mod
72
+ }
73
+ }
74
+ end
75
+
76
+ def batterfly_inv(a, h)
77
+ h.downto(1){ |ph|
78
+ w = 1 << (ph - 1)
79
+ p = 1 << (h - ph)
80
+ inow = 1
81
+ w.times{ |s|
82
+ offset = s << (h - ph + 1)
83
+ offset.upto(offset + p - 1){ |i|
84
+ l = a[i]
85
+ r = a[i + p]
86
+ a[i] = l + r
87
+ a[i + p] = (l - r) * inow % @mod
88
+ }
89
+ inow = inow * @sum_ie[bsf(~s)] % @mod
90
+ }
91
+ }
92
+ end
93
+
94
+ def bsf(x)
95
+ (x & -x).bit_length - 1
96
+ end
97
+
98
+ def calc_primitive_root(mod)
99
+ return 1 if mod == 2
100
+ return 3 if mod == 998_244_353
101
+
102
+ divs = [2]
103
+ x = (mod - 1) / 2
104
+ x /= 2 while x.even?
105
+ i = 3
106
+ while i * i <= x
107
+ if x % i == 0
108
+ divs << i
109
+ x /= i while x % i == 0
110
+ end
111
+ i += 2
112
+ end
113
+ divs << x if x > 1
114
+
115
+ g = 2
116
+ loop{
117
+ return g if divs.none?{ |d| g.pow((mod - 1) / d, mod) == 1 }
118
+
119
+ g += 1
120
+ }
121
+ end
122
+
123
+ private :batterfly, :batterfly_inv, :bsf, :calc_primitive_root
124
+ 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
data/lib/crt.rb ADDED
@@ -0,0 +1,52 @@
1
+ # return [rem, mod] or [0, 0] (if no solution)
2
+ def crt(r, m)
3
+ raise ArgumentError if r.size != m.size
4
+
5
+ n = r.size
6
+ r0, m0 = 0, 1
7
+ n.times do |i|
8
+ raise ArgumentError if m[i] < 1
9
+
10
+ r1, m1 = r[i] % m[i], m[i]
11
+ if m0 < m1
12
+ r0, r1 = r1, r0
13
+ m0, m1 = m1, m0
14
+ end
15
+
16
+ if m0 % m1 == 0
17
+ return [0, 0] if r0 % m1 != r1
18
+
19
+ next
20
+ end
21
+
22
+ g, im = inv_gcd(m0, m1)
23
+ u1 = m1 / g
24
+ return [0, 0] if (r1 - r0) % g != 0
25
+
26
+ x = (r1 - r0) / g * im % u1
27
+ r0 += x * m0
28
+ m0 *= u1
29
+ r0 += m0 if r0 < 0
30
+ end
31
+
32
+ return [r0, m0]
33
+ end
34
+
35
+ # internal method
36
+ # return [g, x] s.t. g = gcd(a, b), x*a = g (mod b), 0 <= x < b/g
37
+ def inv_gcd(a, b)
38
+ a %= b
39
+ return [b, 0] if a == 0
40
+
41
+ s, t = b, a
42
+ m0, m1 = 0, 1
43
+ while t > 0
44
+ u, s = s.divmod(t)
45
+ m0 -= m1 * u
46
+ s, t = t, s
47
+ m0, m1 = m1, m0
48
+ end
49
+ m0 += b / s if m0 < 0
50
+
51
+ return [s, m0]
52
+ end
data/lib/dsu.rb ADDED
@@ -0,0 +1,44 @@
1
+ # Disjoint Set Union
2
+ class DSU
3
+ def initialize(n = 0)
4
+ # root node: -1 * component size
5
+ # otherwise: parent
6
+ @parent_or_size = Array.new(n, -1)
7
+ end
8
+
9
+ attr_accessor :parent_or_size
10
+
11
+ def merge(a, b)
12
+ x = leader(a)
13
+ y = leader(b)
14
+ return x if x == y
15
+
16
+ x, y = y, x if -@parent_or_size[x] < -@parent_or_size[y]
17
+ @parent_or_size[x] += @parent_or_size[y]
18
+ @parent_or_size[y] = x
19
+ end
20
+ alias unite merge
21
+
22
+ def same(a, b)
23
+ leader(a) == leader(b)
24
+ end
25
+ alias same? same
26
+
27
+ def leader(a)
28
+ @parent_or_size[a] < 0 ? a : (@parent_or_size[a] = leader(@parent_or_size[a]))
29
+ end
30
+ alias root leader
31
+ alias find leader
32
+
33
+ def size(a)
34
+ -@parent_or_size[leader(a)]
35
+ end
36
+
37
+ def groups
38
+ (0 ... @parent_or_size.size).group_by{ |i| leader(i) }.values
39
+ end
40
+ end
41
+
42
+ UnionFind = DSU
43
+ UnionFindTree = DSU
44
+ DisjointSetUnion = DSU
@@ -0,0 +1,48 @@
1
+ # Fenwick Tree
2
+ class FenwickTree
3
+ attr_reader :data, :size
4
+
5
+ def initialize(arg = 0)
6
+ case arg
7
+ when Array
8
+ @size = arg.size
9
+ @data = [0].concat(arg)
10
+ (1 ... @size).each do |i|
11
+ up = i + (i & -i)
12
+ next if up > @size
13
+
14
+ @data[up] += @data[i]
15
+ end
16
+ when Integer
17
+ @size = arg
18
+ @data = Array.new(@size + 1, 0)
19
+ else
20
+ raise ArgumentError
21
+ end
22
+ end
23
+
24
+ def add(i, x)
25
+ i += 1
26
+ while i <= @size
27
+ @data[i] += x
28
+ i += (i & -i)
29
+ end
30
+ end
31
+
32
+ def sum(l, r)
33
+ _sum(r) - _sum(l)
34
+ end
35
+
36
+ def _sum(i)
37
+ res = 0
38
+ while i > 0
39
+ res += @data[i]
40
+ i &= i - 1
41
+ end
42
+ res
43
+ end
44
+ end
45
+
46
+ FeTree = FenwickTree
47
+ Fetree = FenwickTree
48
+ BinaryIndexedTree = FenwickTree
data/lib/floor_sum.rb ADDED
@@ -0,0 +1,21 @@
1
+ def floor_sum(n, m, a, b)
2
+ res = 0
3
+
4
+ if a >= m
5
+ res += (n - 1) * n * (a / m) / 2
6
+ a %= m
7
+ end
8
+
9
+ if b >= m
10
+ res += n * (b / m)
11
+ b %= m
12
+ end
13
+
14
+ y_max = (a * n + b) / m
15
+
16
+ return res if y_max == 0
17
+
18
+ x_max = (m * y_max - b + a - 1) / a
19
+ res += (n - x_max) * y_max + floor_sum(y_max, a, m, a * x_max - m * y_max + b)
20
+ res
21
+ end
data/lib/inv_mod.rb ADDED
@@ -0,0 +1,26 @@
1
+ # Use `x.pow(m - 2, m)` instead of `inv_mod(x, m)` if m is a prime number.
2
+ def inv_mod(x, m)
3
+ z = _inv_gcd(x, m)
4
+ raise ArgumentError unless z.first == 1
5
+
6
+ z[1]
7
+ end
8
+
9
+ def _inv_gcd(a, b)
10
+ a %= b # safe_mod
11
+
12
+ s, t = b, a
13
+ m0, m1 = 0, 1
14
+
15
+ while t > 0
16
+ u = s / t
17
+ s -= t * u
18
+ m0 -= m1 * u
19
+
20
+ s, t = t, s
21
+ m0, m1 = m1, m0
22
+ end
23
+
24
+ m0 += b / s if m0 < 0
25
+ [s, m0]
26
+ end
@@ -0,0 +1,149 @@
1
+ # Segment tree with Lazy propagation
2
+ class LazySegtree
3
+ attr_reader :d, :lz
4
+ attr_accessor :op, :mapping, :composition
5
+
6
+ def initialize(v, e, id, op, mapping, composition)
7
+ v = Array.new(v, e) if v.is_a?(Integer)
8
+
9
+ @n = v.size
10
+ @e = e
11
+ @id = id
12
+ @op = op
13
+ @mapping = mapping
14
+ @composition = composition
15
+
16
+ @log = (@n - 1).bit_length
17
+ @size = 1 << @log
18
+ @d = Array.new(2 * @size, e)
19
+ @lz = Array.new(@size, id)
20
+
21
+ @n.times { |i| @d[@size + i] = v[i] }
22
+ (@size - 1).downto(1) { |i| update(i) }
23
+ end
24
+
25
+ def set(pos, x)
26
+ pos += @size
27
+ @log.downto(1) { |i| push(pos >> i) }
28
+ @d[pos] = x
29
+ 1.upto(@log) { |i| update(pos >> i) }
30
+ end
31
+
32
+ def get(pos)
33
+ pos += @size
34
+ @log.downto(1) { |i| push(pos >> i) }
35
+ @d[pos]
36
+ end
37
+
38
+ def prod(l, r)
39
+ return @e if l == r
40
+
41
+ l += @size
42
+ r += @size
43
+
44
+ @log.downto(1) do |i|
45
+ push(l >> i) if (l >> i) << i != l
46
+ push(r >> i) if (r >> i) << i != r
47
+ end
48
+
49
+ sml = @e
50
+ smr = @e
51
+ while l < r
52
+ if l.odd?
53
+ sml = @op.call(sml, @d[l])
54
+ l += 1
55
+ end
56
+ if r.odd?
57
+ r -= 1
58
+ smr = @op.call(@d[r], smr)
59
+ end
60
+ l >>= 1
61
+ r >>= 1
62
+ end
63
+
64
+ @op.call(sml, smr)
65
+ end
66
+
67
+ def all_prod
68
+ @d[1]
69
+ end
70
+
71
+ def apply(pos, f)
72
+ pos += @size
73
+ @log.downto(1) { |i| push(pos >> i) }
74
+ @d[pos] = @mapping.call(f, @d[pos])
75
+ 1.upto(@log) { |i| update(pos >> i) }
76
+ end
77
+
78
+ def range_apply(l, r, f)
79
+ return if l == r
80
+
81
+ l += @size
82
+ r += @size
83
+
84
+ @log.downto(1) do |i|
85
+ push(l >> i) if (l >> i) << i != l
86
+ push((r - 1) >> i) if (r >> i) << i != r
87
+ end
88
+
89
+ l2 = l
90
+ r2 = r
91
+ while l < r
92
+ (all_apply(l, f); l += 1) if l.odd?
93
+ (r -= 1; all_apply(r, f)) if r.odd?
94
+ l >>= 1
95
+ r >>= 1
96
+ end
97
+ l = l2
98
+ r = r2
99
+
100
+ 1.upto(@log) do |i|
101
+ update(l >> i) if (l >> i) << i != l
102
+ update((r - 1) >> i) if (r >> i) << i != r
103
+ end
104
+ end
105
+
106
+ def max_right(l, &g)
107
+ return @n if l == @n
108
+
109
+ l += @size
110
+ @log.downto(1) { |i| push(l >> i) }
111
+ sm = @e
112
+
113
+ loop do
114
+ while l.even?
115
+ l >>= 1
116
+ end
117
+ unless g.call(@op.call(sm, @d[l]))
118
+ while l < @size
119
+ push(l)
120
+ l <<= 1
121
+ if g.call(@op.call(sm, @d[l]))
122
+ sm = @op.call(sm, @d[l])
123
+ l += 1
124
+ end
125
+ end
126
+ return l - @size
127
+ end
128
+ sm = @op.call(sm, @d[l])
129
+ l += 1
130
+ break if l & -l == l
131
+ end
132
+ @n
133
+ end
134
+
135
+ def update(k)
136
+ @d[k] = @op.call(@d[2 * k], @d[2 * k + 1])
137
+ end
138
+
139
+ def all_apply(k, f)
140
+ @d[k] = @mapping.call(f, @d[k])
141
+ @lz[k] = @composition.call(f, @lz[k]) if k < @size
142
+ end
143
+
144
+ def push(k)
145
+ all_apply(2 * k, @lz[k])
146
+ all_apply(2 * k + 1, @lz[k])
147
+ @lz[k] = @id
148
+ end
149
+ end