ac-library-rb 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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