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,172 @@
1
+ module AcLibraryRb
2
+ require_relative './core_ext/modint.rb'
3
+
4
+ # ModInt
5
+ class ModInt < Numeric
6
+ class << self
7
+ def set_mod(mod)
8
+ raise ArgumentError unless mod.is_a? Integer and 1 <= mod
9
+
10
+ $_mod = mod
11
+ $_mod_is_prime = ModInt.prime?(mod)
12
+ end
13
+
14
+ def mod=(mod)
15
+ set_mod mod
16
+ end
17
+
18
+ def mod
19
+ $_mod
20
+ end
21
+
22
+ def raw(val)
23
+ x = allocate
24
+ x.val = val.to_i
25
+ x
26
+ end
27
+
28
+ def prime?(n)
29
+ return false if n <= 1
30
+ return true if n == 2 or n == 7 or n == 61
31
+ return false if (n & 1) == 0
32
+
33
+ d = n - 1
34
+ d >>= 1 while (d & 1) == 0
35
+ [2, 7, 61].each do |a|
36
+ t = d
37
+ y = a.pow(t, n)
38
+ while t != n - 1 and y != 1 and y != n - 1
39
+ y = y * y % n
40
+ t <<= 1
41
+ end
42
+ return false if y != n - 1 and (t & 1) == 0
43
+ end
44
+ true
45
+ end
46
+
47
+ def inv_gcd(a, b)
48
+ a %= b
49
+ return [b, 0] if a == 0
50
+
51
+ s, t = b, a
52
+ m0, m1 = 0, 1
53
+ while t != 0
54
+ u = s / t
55
+ s -= t * u
56
+ m0 -= m1 * u
57
+ s, t = t, s
58
+ m0, m1 = m1, m0
59
+ end
60
+ m0 += b / s if m0 < 0
61
+ [s, m0]
62
+ end
63
+ end
64
+
65
+ attr_accessor :val
66
+
67
+ alias to_i val
68
+
69
+ def initialize(val = 0)
70
+ @val = val.to_i % $_mod
71
+ end
72
+
73
+ def inc!
74
+ @val += 1
75
+ @val = 0 if @val == $_mod
76
+ self
77
+ end
78
+
79
+ def dec!
80
+ @val = $_mod if @val == 0
81
+ @val -= 1
82
+ self
83
+ end
84
+
85
+ def add!(other)
86
+ @val = (@val + other.to_i) % $_mod
87
+ self
88
+ end
89
+
90
+ def sub!(other)
91
+ @val = (@val - other.to_i) % $_mod
92
+ self
93
+ end
94
+
95
+ def mul!(other)
96
+ @val = @val * other.to_i % $_mod
97
+ self
98
+ end
99
+
100
+ def div!(other)
101
+ mul! inv_internal(other.to_i)
102
+ end
103
+
104
+ def +@
105
+ self
106
+ end
107
+
108
+ def -@
109
+ ModInt.raw($_mod - @val)
110
+ end
111
+
112
+ def **(other)
113
+ $_mod == 1 ? 0 : ModInt.raw(@val.pow(other, $_mod))
114
+ end
115
+ alias pow **
116
+
117
+ def inv
118
+ ModInt.raw(inv_internal(@val) % $_mod)
119
+ end
120
+
121
+ def coerce(other)
122
+ [ModInt(other), self]
123
+ end
124
+
125
+ def +(other)
126
+ dup.add! other
127
+ end
128
+
129
+ def -(other)
130
+ dup.sub! other
131
+ end
132
+
133
+ def *(other)
134
+ dup.mul! other
135
+ end
136
+
137
+ def /(other)
138
+ dup.div! other
139
+ end
140
+
141
+ def ==(other)
142
+ @val == other.to_i
143
+ end
144
+
145
+ def dup
146
+ ModInt.raw(@val)
147
+ end
148
+
149
+ def to_int
150
+ @val
151
+ end
152
+
153
+ def to_s
154
+ @val.to_s
155
+ end
156
+
157
+ def inspect
158
+ "#{@val} mod #{$_mod}"
159
+ end
160
+
161
+ private
162
+
163
+ def inv_internal(a)
164
+ if $_mod_is_prime
165
+ a != 0 ? a.pow($_mod - 2, $_mod) : raise(RangeError, 'no inverse')
166
+ else
167
+ g, x = ModInt.inv_gcd(a, $_mod)
168
+ g == 1 ? x : raise(RangeError, 'no inverse')
169
+ end
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,15 @@
1
+ module AcLibraryRb
2
+ # Use `Integer#pow` unless m == 1
3
+ def pow_mod(x, n, m)
4
+ return 0 if m == 1
5
+
6
+ r, y = 1, x % m
7
+ while n > 0
8
+ r = r * y % m if n.odd?
9
+ y = y * y % m
10
+ n >>= 1
11
+ end
12
+
13
+ r
14
+ end
15
+ end
@@ -0,0 +1,91 @@
1
+ module AcLibraryRb
2
+ # Priority Queue
3
+ # Reference: https://github.com/python/cpython/blob/master/Lib/heapq.py
4
+ class PriorityQueue
5
+ # By default, the priority queue returns the maximum element first.
6
+ # If a block is given, the priority between the elements is determined with it.
7
+ # For example, the following block is given, the priority queue returns the minimum element first.
8
+ # `PriorityQueue.new { |x, y| x < y }`
9
+ #
10
+ # A heap is an array for which a[k] <= a[2*k+1] and a[k] <= a[2*k+2] for all k, counting elements from 0.
11
+ def initialize(array = [], &comp)
12
+ @heap = array
13
+ @comp = comp || proc { |x, y| x > y }
14
+ heapify
15
+ end
16
+
17
+ attr_reader :heap
18
+
19
+ # Push new element to the heap.
20
+ def push(item)
21
+ shift_down(0, @heap.push(item).size - 1)
22
+ end
23
+
24
+ alias << push
25
+ alias append push
26
+
27
+ # Pop the element with the highest priority.
28
+ def pop
29
+ latest = @heap.pop
30
+ return latest if empty?
31
+
32
+ ret_item = heap[0]
33
+ heap[0] = latest
34
+ shift_up(0)
35
+ ret_item
36
+ end
37
+
38
+ # Get the element with the highest priority.
39
+ def get
40
+ @heap[0]
41
+ end
42
+
43
+ alias top get
44
+
45
+ # Returns true if the heap is empty.
46
+ def empty?
47
+ @heap.empty?
48
+ end
49
+
50
+ private
51
+
52
+ def heapify
53
+ (@heap.size / 2 - 1).downto(0) { |i| shift_up(i) }
54
+ end
55
+
56
+ def shift_up(pos)
57
+ end_pos = @heap.size
58
+ start_pos = pos
59
+ new_item = @heap[pos]
60
+ left_child_pos = 2 * pos + 1
61
+
62
+ while left_child_pos < end_pos
63
+ right_child_pos = left_child_pos + 1
64
+ if right_child_pos < end_pos && @comp.call(@heap[right_child_pos], @heap[left_child_pos])
65
+ left_child_pos = right_child_pos
66
+ end
67
+ # Move the higher priority child up.
68
+ @heap[pos] = @heap[left_child_pos]
69
+ pos = left_child_pos
70
+ left_child_pos = 2 * pos + 1
71
+ end
72
+ @heap[pos] = new_item
73
+ shift_down(start_pos, pos)
74
+ end
75
+
76
+ def shift_down(star_pos, pos)
77
+ new_item = @heap[pos]
78
+ while pos > star_pos
79
+ parent_pos = (pos - 1) >> 1
80
+ parent = @heap[parent_pos]
81
+ break if @comp.call(parent, new_item)
82
+
83
+ @heap[pos] = parent
84
+ pos = parent_pos
85
+ end
86
+ @heap[pos] = new_item
87
+ end
88
+ end
89
+
90
+ HeapQueue = PriorityQueue
91
+ end
@@ -0,0 +1,79 @@
1
+ module AcLibraryRb
2
+ # Strongly Connected Components
3
+ class SCCGraph
4
+ # initialize graph with n vertices
5
+ def initialize(n = 0)
6
+ @n, @edges = n, []
7
+ end
8
+
9
+ # add directed edge
10
+ def add_edge(from, to)
11
+ raise "invalid params" unless (0...@n).include? from and (0...@n).include? to
12
+
13
+ @edges << [from, to]
14
+ end
15
+
16
+ # returns list of strongly connected components
17
+ # the components are sorted in topological order
18
+ # O(@n + @edges.size)
19
+ def scc
20
+ group_num, ids = scc_ids
21
+ counts = [0] * group_num
22
+ ids.each { |x| counts[x] += 1 }
23
+ groups = Array.new(group_num) { [] }
24
+ ids.each_with_index { |x, i| groups[x] << i }
25
+ groups
26
+ end
27
+
28
+ private
29
+
30
+ def scc_ids
31
+ start, elist = csr
32
+ now_ord = group_num = 0
33
+ visited, low, ord, ids = [], [], [-1] * @n, []
34
+ dfs = ->(v) {
35
+ low[v] = ord[v] = now_ord
36
+ now_ord += 1
37
+ visited << v
38
+ (start[v]...start[v + 1]).each do |i|
39
+ to = elist[i]
40
+ low[v] = if ord[to] == -1
41
+ dfs.(to)
42
+ [low[v], low[to]].min
43
+ else
44
+ [low[v], ord[to]].min
45
+ end
46
+ end
47
+ if low[v] == ord[v]
48
+ loop do
49
+ u = visited.pop
50
+ ord[u] = @n
51
+ ids[u] = group_num
52
+ break if u == v
53
+ end
54
+ group_num += 1
55
+ end
56
+ }
57
+ @n.times { |i| dfs.(i) if ord[i] == -1 }
58
+ ids = ids.map { |x| group_num - 1 - x }
59
+ [group_num, ids]
60
+ end
61
+
62
+ def csr
63
+ start, elist = [0] * (@n + 1), [nil] * @edges.size
64
+ @edges.each { |(i, _)| start[i + 1] += 1 }
65
+ @n.times { |i| start[i + 1] += start[i] }
66
+ counter = start.dup
67
+ @edges.each do |(i, j)|
68
+ elist[counter[i]] = j
69
+ counter[i] += 1
70
+ end
71
+ [start, elist]
72
+ end
73
+ end
74
+
75
+ # class alias
76
+ StronglyConnectedComponents = SCCGraph
77
+ SCC = SCCGraph
78
+ SCCG = SCCGraph
79
+ end
@@ -0,0 +1,142 @@
1
+ module AcLibraryRb
2
+ # Segment Tree
3
+ class Segtree
4
+ attr_reader :d, :op, :n, :leaf_size, :log
5
+
6
+ def initialize(arg = 0, e, &block)
7
+ case arg
8
+ when Integer
9
+ v = Array.new(arg) { e }
10
+ when Array
11
+ v = arg
12
+ end
13
+
14
+ @e = e
15
+ @op = proc(&block)
16
+
17
+ @n = v.size
18
+ @log = (@n - 1).bit_length
19
+ @leaf_size = 1 << @log
20
+ @d = Array.new(@leaf_size * 2) { e }
21
+ v.each_with_index { |v_i, i| @d[@leaf_size + i] = v_i }
22
+ (@leaf_size - 1).downto(1) { |i| update(i) }
23
+ end
24
+
25
+ def set(q, x)
26
+ q += @leaf_size
27
+ @d[q] = x
28
+ 1.upto(@log) { |i| update(q >> i) }
29
+ end
30
+
31
+ def get(pos)
32
+ @d[@leaf_size + pos]
33
+ end
34
+
35
+ def prod(l, r)
36
+ return @e if l == r
37
+
38
+ sml = @e
39
+ smr = @e
40
+ l += @leaf_size
41
+ r += @leaf_size
42
+
43
+ while l < r
44
+ if l[0] == 1
45
+ sml = @op.call(sml, @d[l])
46
+ l += 1
47
+ end
48
+ if r[0] == 1
49
+ r -= 1
50
+ smr = @op.call(@d[r], smr)
51
+ end
52
+ l /= 2
53
+ r /= 2
54
+ end
55
+
56
+ @op.call(sml, smr)
57
+ end
58
+
59
+ def all_prod
60
+ @d[1]
61
+ end
62
+
63
+ def max_right(l, &block)
64
+ return @n if l == @n
65
+
66
+ f = proc(&block)
67
+
68
+ l += @leaf_size
69
+ sm = @e
70
+ loop do
71
+ l /= 2 while l.even?
72
+ unless f.call(@op.call(sm, @d[l]))
73
+ while l < @leaf_size
74
+ l *= 2
75
+ if f.call(@op.call(sm, @d[l]))
76
+ sm = @op.call(sm, @d[l])
77
+ l += 1
78
+ end
79
+ end
80
+
81
+ return l - @leaf_size
82
+ end
83
+
84
+ sm = @op.call(sm, @d[l])
85
+ l += 1
86
+ break if (l & -l) == l
87
+ end
88
+
89
+ @n
90
+ end
91
+
92
+ def min_left(r, &block)
93
+ return 0 if r == 0
94
+
95
+ f = proc(&block)
96
+
97
+ r += @leaf_size
98
+ sm = @e
99
+ loop do
100
+ r -= 1
101
+ r /= 2 while r > 1 && r.odd?
102
+ unless f.call(@op.call(@d[r], sm))
103
+ while r < @leaf_size
104
+ r = r * 2 + 1
105
+ if f.call(@op.call(@d[r], sm))
106
+ sm = @op.call(@d[r], sm)
107
+ r -= 1
108
+ end
109
+ end
110
+
111
+ return r + 1 - @leaf_size
112
+ end
113
+
114
+ sm = @op.call(@d[r], sm)
115
+ break if (r & -r) == r
116
+ end
117
+
118
+ 0
119
+ end
120
+
121
+ def update(k)
122
+ @d[k] = @op.call(@d[2 * k], @d[2 * k + 1])
123
+ end
124
+
125
+ def inspect
126
+ t = 0
127
+ res = "SegmentTree @e = #{@e}, @n = #{@n}, @leaf_size = #{@leaf_size} @op = #{@op}\n "
128
+ a = @d[1, @d.size - 1]
129
+ a.each_with_index do |e, i|
130
+ res << e.to_s << ' '
131
+ if t == i && i < @leaf_size
132
+ res << "\n "
133
+ t = t * 2 + 2
134
+ end
135
+ end
136
+ res
137
+ end
138
+ end
139
+
140
+ SegTree = Segtree
141
+ SegmentTree = Segtree
142
+ end