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