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
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
@@ -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