This documentation is automatically generated by online-judge-tools/verification-helper
# ac-library.cr by hakatashi https://github.com/google/ac-library.cr # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. require "./*"
# ac-library.cr by hakatashi https://github.com/google/ac-library.cr # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require "./*" # ac-library.cr by hakatashi https://github.com/google/ac-library.cr # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. module AtCoder # Implements [atcoder::convolution](https://atcoder.github.io/ac-library/master/document_en/convolution.html). # # ``` # a = [AtCoder::ModInt998244353.new(1_i64)] * 3 # AtCoder::Convolution.convolution(a, a) # => [1, 2, 3, 2, 1] # ``` module Convolution private def self.bit_reverse(n : Int, bit_length : Int) ret = n.class.zero bit_length.times do |i| ret |= ((n >> i) & 1) << (bit_length - i - 1) end ret end # In-place execution of FFT operation. # `T` must implement ModInt operations. # Length of `a` must be power of 2. private def self.fft(a : Array(T), g : T) forall T size = a.size bit_length = size.trailing_zeros_count size.times do |i| j = bit_reverse(i, bit_length) if i < j a[i], a[j] = a[j], a[i] end end bit_length.times do |bit| block_size = 1_i64 << bit # Butterfly operation block_size.times do |i| w = (g ** (size // block_size // 2)) ** i (size // (block_size * 2)).times do |j| index1 = j * 2 * block_size + i index2 = (j * 2 + 1) * block_size + i a[index1], a[index2] = { a[index1] + a[index2] * w, a[index1] - a[index2] * w, } end end end end private def self.ifft(a, g) fft(a, g.inv) a.size.times do |i| a[i] //= a.size end end # Implements atcoder::convolution.convolution. # TODO: Support for int def self.convolution(a : Array(T), b : Array(T)) forall T return [] of T if a.empty? || b.empty? modulo = T::MOD n = modulo - 1 result_size = a.size + b.size - 1 c = 1_i64 << n.trailing_zeros_count if result_size > c raise ArgumentError.new("With modulo #{modulo}, total array length must be less than or equal to #{c}") end fft_size = 1_i64 until fft_size >= result_size fft_size <<= 1 end input_a = Array(T).new(fft_size) { |i| i < a.size ? a[i] : T.zero } input_b = Array(T).new(fft_size) { |i| i < b.size ? b[i] : T.zero } primitive_root = AtCoder::Math.get_primitive_root(modulo) g = T.new(primitive_root) ** (n // fft_size) fft(input_a, g) fft(input_b, g) fft_size.times do |i| input_a[i] *= input_b[i] end ifft(input_a, g) input_a[0...result_size] end # Implements atcoder::convolution.convolution_ll. def self.convolution_ll(a : Array(Int64), b : Array(Int64)) return [] of Int64 if a.empty? || b.empty? a1 = a.map { |n| AtCoder::ModInt754974721.new(n) } a2 = a.map { |n| AtCoder::ModInt167772161.new(n) } a3 = a.map { |n| AtCoder::ModInt469762049.new(n) } b1 = b.map { |n| AtCoder::ModInt754974721.new(n) } b2 = b.map { |n| AtCoder::ModInt167772161.new(n) } b3 = b.map { |n| AtCoder::ModInt469762049.new(n) } c1 = convolution(a1, b1) c2 = convolution(a2, b2) c3 = convolution(a3, b3) m1 = 754_974_721_i64 m2 = 167_772_161_i64 m3 = 469_762_049_i64 c1.zip(c2, c3).map do |n1, n2, n3| p = AtCoder::Math.inv_mod(m1, m2) tmp = (n2.val - n1.val) * p % m2 answer = n1.val + m1 * tmp p = AtCoder::Math.inv_mod(m1 * m2, m3) tmp = (((n3.val - answer) % m3) * p) % m3 answer + m1 * m2 * tmp end end end end # ac-library.cr by hakatashi https://github.com/google/ac-library.cr # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. module AtCoder # Implements [atcoder::dsu](https://atcoder.github.io/ac-library/master/document_en/dsu.html). # # ``` # dsu = AtCoder::DSU.new(10) # dsu.merge(0, 2) # dsu.merge(4, 2) # dsu.same?(0, 4) # => true # dsu.size(4) # => 3 # ``` class DSU getter parents : Array(Int64) getter sizes : Array(Int64) getter size : Int64 def initialize(@size) @parents = Array.new(size, &.to_i64) @sizes = Array.new(size, 1_i64) end # Implements atcoder::dsu.leader(node). def leader(node) until @parents[node] == node @parents[node] = @parents[@parents[node]] node = @parents[node] end node end # Implements atcoder::dsu.merge(a, b). def merge(a, b) leader_a = leader(a.to_i64) leader_b = leader(b.to_i64) unless leader_a == leader_b if @sizes[leader_a] < @sizes[leader_b] leader_a, leader_b = leader_b, leader_a end @parents[leader_b] = leader_a @sizes[leader_a] += @sizes[leader_b] end end # Implements atcoder::dsu.same(a, b). def same?(a, b) leader(a) == leader(b) end # Implements atcoder::dsu.size(). def size(node) @sizes[leader(node)] end # Implements atcoder::dsu.groups(). # This method returns `Set` instead of list. def groups groups = Hash(Int64, Set(Int64)).new { |h, k| h[k] = Set(Int64).new } @size.times do |i| groups[leader(i)] << i end groups.values.to_set end end end # ac-library.cr by hakatashi https://github.com/google/ac-library.cr # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. module AtCoder # Implements [atcoder::fenwick_tree](https://atcoder.github.io/ac-library/master/document_en/fenwicktree.html). # # ``` # tree = AtCoder::FenwickTree(Int64).new(10) # tree.add(3, 10) # tree.add(5, 20) # tree[3..5] # => 30 # tree[3...5] # => 10 # ``` class FenwickTree(T) getter size : Int64 getter bits : Array(T) def initialize(@size : Int64) @bits = Array(T).new(@size, T.zero) end def initialize(@bits : Array) @bits = @bits.dup @size = @bits.size.to_i64 (1...@size).each do |index| up = index + (index & -index) next if up > @size @bits[up - 1] += @bits[index - 1] end end # Implements atcoder::fenwick_tree.add(index, value) def add(index, value) index += 1 # convert to 1-indexed while index <= @size @bits[index - 1] += value index += index & -index end end # Exclusive left sum def left_sum(index) ret = T.zero while index >= 1 ret += @bits[index - 1] index -= index & -index end ret end # Implements atcoder::fenwick_tree.sum(left, right) def sum(left, right) left_sum(right) - left_sum(left) end # Implements atcoder::fenwick_tree.sum(left, right) # # Open ended ranges are clamped at the start and end of array, respectively. def sum(range : Range) left = range.begin || 0 right = range.exclusive? ? (range.end || @size) : (range.end || @size - 1) + 1 sum(left, right) end # :ditto: def [](range : Range) sum(range) end end end # ac-library.cr by hakatashi https://github.com/google/ac-library.cr # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require "./priority_queue.cr" # ac-library.cr by hakatashi https://github.com/google/ac-library.cr # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. module AtCoder # Implements standard priority queue like [std::priority_queue](https://en.cppreference.com/w/cpp/container/priority_queue). # # ``` # q = AtCoder::PriorityQueue(Int64).new # q << 1_i64 # q << 3_i64 # q << 2_i64 # q.pop # => 3 # q.pop # => 2 # q.pop # => 1 # ``` class PriorityQueue(T) include Enumerable(T) getter heap : Array(T) # Create a new queue in ascending order of priority. def self.max self.new { |a, b| a <= b } end # Create a new queue in ascending order of priority with the elements in *enumerable*. def self.max(enumerable : Enumerable(T)) self.new(enumerable) { |a, b| a <= b } end # Create a new queue in descending order of priority. def self.min self.new { |a, b| a >= b } end # Create a new queue in descending order of priority with the elements in *enumerable*. def self.min(enumerable : Enumerable(T)) self.new(enumerable) { |a, b| a >= b } end def initialize initialize { |a, b| a <= b } end # Initializes queue with the elements in *enumerable*. def self.new(enumerable : Enumerable(T)) self.new(enumerable) { |a, b| a <= b } end # Initializes queue with the custom comperator. # # If the second argument `b` should be popped earlier than # the first argument `a`, return `true`. Else, return `false`. # # ``` # q = AtCoder::PriorityQueue(Int64).new { |a, b| a >= b } # q << 1_i64 # q << 3_i64 # q << 2_i64 # q.pop # => 1 # q.pop # => 2 # q.pop # => 3 # ``` def initialize(&block : T, T -> Bool) @heap = Array(T).new @compare_proc = block end # Initializes queue with the elements in *enumerable* and the custom comperator. # # If the second argument `b` should be popped earlier than # the first argument `a`, return `true`. Else, return `false`. # # ``` # q = AtCoder::PriorityQueue.new([1, 3, 2]) { |a, b| a >= b } # q.pop # => 1 # q.pop # => 2 # q.pop # => 3 # ``` def initialize(enumerable : Enumerable(T), &block : T, T -> Bool) @heap = enumerable.to_a @compare_proc = block len = @heap.size (len // 2 - 1).downto(0) do |parent| v = @heap[parent] child = parent * 2 + 1 while child < len if child + 1 < len && @compare_proc.call(@heap[child], @heap[child + 1]) child += 1 end unless @compare_proc.call(v, @heap[child]) break end @heap[parent] = @heap[child] parent = child child = parent * 2 + 1 end @heap[parent] = v end end # Pushes value into the queue. # This method returns self, so several calls can be chained. def push(v : T) : self @heap << v index = @heap.size - 1 while index != 0 parent = (index - 1) // 2 if @compare_proc.call(@heap[index], @heap[parent]) break end @heap[parent], @heap[index] = @heap[index], @heap[parent] index = parent end self end # Alias of `push` def <<(v : T) : self push(v) end # Pops value from the queue. def pop if @heap.size == 0 return nil end if @heap.size == 1 return @heap.pop end ret = @heap.first @heap[0] = @heap.pop index = 0 while index * 2 + 1 < @heap.size child = if index * 2 + 2 < @heap.size && !@compare_proc.call(@heap[index * 2 + 2], @heap[index * 2 + 1]) index * 2 + 2 else index * 2 + 1 end if @compare_proc.call(@heap[child], @heap[index]) break end @heap[child], @heap[index] = @heap[index], @heap[child] index = child end ret end # Pops value from the queue. # Raises `Enumerable::EmptyError` if queue is of 0 size. def pop! pop || raise Enumerable::EmptyError.new end # Yields each item in the queue in comparator's order. def each(&) @heap.sort { |a, b| @compare_proc.call(a, b) ? 1 : -1 }.each do |e| yield e end end # Returns, but does not remove, the head of the queue. def first(&) @heap.first { yield } end # Returns `true` if the queue is empty. delegate :empty?, to: @heap # Returns size of the queue. delegate :size, to: @heap end end module AtCoder class Graph(NodeInfo, EdgeInfo) @size_bits : Int32 getter visited : Set(Int64) def initialize(@nodes : Array(NodeInfo)) @size = @nodes.size.to_i64 @edges = [] of EdgeInfo @adjacencies = Array(Hash(Int64, Int64)).new(@size) { Hash(Int64, Int64).new } @visited = Set(Int64).new @size_bits = @size.to_s(2).size end def initialize(@size : Int64, initial_node : NodeInfo = nil) @nodes = Array(NodeInfo).new(@size, initial_node) @edges = [] of EdgeInfo @adjacencies = Array(Hash(Int64, Int64)).new(@size) { Hash(Int64, Int64).new } @visited = Set(Int64).new @size_bits = @size.to_s(2).size end # Performs Dijkstra's Algorithm to calculate the distance of each node from `start_node`. # To use this method, `EdgeInfo` must implement `.zero` and `#+(EdgeInfo)` and `#>(EdgeInfo)`. def dijkstra(start_node) dist = Array(EdgeInfo | Nil).new(@size, nil) dist[start_node] = EdgeInfo.zero prev_nodes = Array(Int64 | Nil).new(@size, nil) queue = AtCoder::PriorityQueue({EdgeInfo, Int64}).new { |(ad, av), (bd, bv)| ad > bd } queue << {EdgeInfo.zero, start_node.to_i64} until queue.empty? d, v = queue.pop.not_nil! current_dist = dist[v].not_nil! next if d > current_dist @adjacencies[v].each do |(to, edge_id)| cost = @edges[edge_id] target_dist = dist[to] if target_dist.nil? || target_dist > current_dist + cost dist[to] = current_dist + cost prev_nodes[to] = v queue << {current_dist + cost, to} end end end Array({dist: EdgeInfo | Nil, prev: Int64 | Nil}).new(@size) do |i| {dist: dist[i], prev: prev_nodes[i]} end end def dfs(node : Int64, initial_value : T, &block : Int64, T, NamedTuple( node: Int64, node_info: NodeInfo | Nil, edge: Int64 | Nil, edge_info: EdgeInfo | Nil, parent: Int64, ), (T ->) ->) forall T @visited = Set(Int64).new info = { node: node, node_info: @nodes[node].as(NodeInfo | Nil), edge: nil.as(Int64 | Nil), edge_info: nil.as(EdgeInfo | Nil), parent: -1_i64, } block.call(node, initial_value, info, ->(new_value : T) { dfs(node, -1_i64, new_value, &block) }) end private def dfs(node : Int64, parent : Int64, value : T, &block : Int64, T, NamedTuple( node: Int64, node_info: NodeInfo | Nil, edge: Int64 | Nil, edge_info: EdgeInfo | Nil, parent: Int64, ), (T ->) ->) forall T @visited << node @adjacencies[node].each do |(child, edge)| next if @visited.includes?(child) info = { node: child, node_info: @nodes[child].as(NodeInfo | Nil), edge: edge.as(Int64 | Nil), edge_info: @edges[edge].as(EdgeInfo | Nil), parent: node, } block.call(child, value, info, ->(new_value : T) { dfs(child, node, new_value, &block) }) end end end class DirectedGraph(NodeInfo, EdgeInfo) < Graph(NodeInfo, EdgeInfo) def add_edge(from, to, edge : EdgeInfo = 1_i64) @edges << edge edge_id = @edges.size.to_i64 - 1 @adjacencies[from][to.to_i64] = edge_id edge_id end def get_edge(from, to) edge_id = @adjacencies[from][to.to_i64] @edges[edge_id] end def update_edge(from, to, edge : EdgeInfo = 1_i64) edge_id = @adjacencies[from][to.to_i64] @edges[edge_id] = edge edge_id end end class UndirectedGraph(NodeInfo, EdgeInfo) < Graph(NodeInfo, EdgeInfo) def add_edge(a, b, edge : EdgeInfo = 1_i64) @edges << edge edge_id = @edges.size.to_i64 - 1 @adjacencies[a][b.to_i64] = edge_id @adjacencies[b][a.to_i64] = edge_id edge_id end def get_edge(a, b) edge_id = @adjacencies[a][b.to_i64] @edges[edge_id] end def update_edge(a, b, edge : EdgeInfo = 1_i64) edge_id = @adjacencies[a][b.to_i64] @edges[edge_id] = edge edge_id end end class Tree(NodeInfo, EdgeInfo) < UndirectedGraph(NodeInfo, EdgeInfo) @lca_root : Int64 | Nil @lca_ancestors : Array(Array(Int64)) | Nil @lca_depths : Array(Int64) | Nil def diameter @farthest_node = -1_i64 @farthest_depth = 0_i64 dfs(0_i64, 0_i64) do |node, depth, info, callback| weight = info[:edge_info] depth += weight.nil? ? 0 : weight if @farthest_depth.not_nil! < depth @farthest_node = node @farthest_depth = depth end callback.call(depth) end start_node = @farthest_node.not_nil! @farthest_node = -1_i64 @farthest_depth = 0_i64 @parents = Array(Int64).new(@size, -1_i64) dfs(start_node, 0_i64) do |node, depth, info, callback| weight = info[:edge_info] depth += weight.nil? ? 0 : weight @parents.not_nil![node] = info[:parent] if @farthest_depth.not_nil! < depth @farthest_node = node @farthest_depth = depth end callback.call(depth) end {@farthest_depth.not_nil!, start_node, @farthest_node.not_nil!, @parents.not_nil!} end private def lca_precompute(root) lca_ancestors = Array(Array(Int64)).new(@size) { Array(Int64).new(@size_bits, -1_i64) } lca_depths = Array(Int64).new(@size, -1_i64) dfs(root, 0_i64) do |node, depth, info, callback| lca_ancestors[node][0] = info[:parent] lca_depths[node] = depth callback.call(depth + 1) end 1.upto(@size_bits - 1) do |i| @size.times do |node| if lca_ancestors[node][i - 1] == -1 lca_ancestors[node][i] = -1_i64 else lca_ancestors[node][i] = lca_ancestors[lca_ancestors[node][i - 1]][i - 1] end end end @lca_root = root @lca_ancestors = lca_ancestors @lca_depths = lca_depths end private def lca_nth_prev(node, dist) lca_ancestors = @lca_ancestors.not_nil! i = 0_i64 until dist == 0 if dist.odd? node = lca_ancestors[node][i] if node == -1 raise Exception.new("#{dist}th previous node of #{node} does not exist") end end dist //= 2 i += 1 end node end # ameba:disable Metrics/CyclomaticComplexity def lca(a, b) if @lca_root.nil? lca_precompute(0_i64) end lca_ancestors = @lca_ancestors.not_nil! lca_depths = @lca_depths.not_nil! depth_a = lca_depths[a] depth_b = lca_depths[b] if depth_a < depth_b depth_a, depth_b, a, b = depth_b, depth_a, b, a end if depth_a != depth_b a = lca_nth_prev(a, depth_a - depth_b) end if a == b return a end (@size_bits - 1).downto(0) do |i| if lca_ancestors[a][i] == -1 || lca_ancestors[b][i] == -1 next end if lca_ancestors[a][i] != lca_ancestors[b][i] a = lca_ancestors[a][i] b = lca_ancestors[b][i] end end a = lca_ancestors[a][0] b = lca_ancestors[b][0] if a != b || a == -1 || b == -1 raise Exception.new("Assertion error") end a end def dist(a, b) lca_node = lca(a, b) lca_depths = @lca_depths.not_nil! (lca_depths[a] - lca_depths[lca_node]) + (lca_depths[b] - lca_depths[lca_node]) end # Returns `true` if node `c` is on the path from `a` to `b`. def on_path?(a, b, c) dist(a, c) + dist(c, b) == dist(a, b) end end end # ac-library.cr by hakatashi https://github.com/google/ac-library.cr # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. module AtCoder # Implements [atcoder::lazy_segtree](https://atcoder.github.io/ac-library/master/document_en/lazysegtree.html). # # The identity element will be implicitly defined as nil, so you don't # have to manually define it. In the other words, you cannot include # nil into an element of the monoid. # # Similarly, the identity map of F will be implicitly defined as nil, # so you don't have to manually define it. In the other words, you # cannot include nil into an element of the set F. # # ``` # op = ->(a : Int32, b : Int32) { [a, b].min } # mapping = ->(f : Int32, x : Int32) { f } # composition = ->(a : Int32, b : Int32) { a } # tree = AtCoder::LazySegTree(Int32, Int32).new((0...100).to_a, op, mapping, composition) # tree[10...50] # => 10 # tree[20...60] = 0 # tree[50...80] # => 0 # ``` class LazySegTree(S, F) @n : Int32 @height : Int32 @n_leaves : Int32 def initialize(values : Array(S), @operator : S, S -> S, @application : F, S -> S, @composition : F, F -> F) @n = values.size @height = log2_ceil(@n) @n_leaves = 1 << @height @segments = Array(S | Nil).new(2 * @n_leaves, nil) @applicators = Array(F | Nil).new(@n_leaves, nil) # initialize segments values.each_with_index { |x, i| @segments[@n_leaves + i] = x.as(S | Nil) } (@n_leaves - 1).downto(1) { |i| refresh(i) } end # Implements atcoder::lazy_segtree.set(index, applicator). def set(index : Int, value : S) index += @n_leaves @height.downto(1) { |j| propagate(ancestor(index, j)) } @segments[index] = value.as(S | Nil) (1..@height).each { |j| refresh(ancestor(index, j)) } end # Implements atcoder::lazy_segtree.apply(index, applicator). def []=(index : Int, applicator : F) index += @n_leaves @height.downto(1) { |j| propagate(ancestor(index, j)) } @segments[index] = apply(applicator, @segments[index]) (1..@height).each { |j| refresh(ancestor(index, j)) } applicator end # Implements atcoder::lazy_segtree.apply(left, right, applicator). # ameba:disable Metrics/CyclomaticComplexity def []=(range : Range, applicator : F) l = (range.begin || 0) + @n_leaves r = (range.exclusive? ? (range.end || @n_leaves) : (range.end || @n_leaves - 1) + 1) + @n_leaves @height.downto(1) do |i| propagate(ancestor(l, i)) if right_side_child?(l, i) propagate(ancestor(r - 1, i)) if right_side_child?(r, i) end l2, r2 = l, r while l2 < r2 if l2.odd? all_apply(l2, applicator) l2 += 1 end if r2.odd? r2 -= 1 all_apply(r2, applicator) end l2 >>= 1 r2 >>= 1 end (1..@height).each do |i| refresh(ancestor(l, i)) if right_side_child?(l, i) refresh(ancestor(r - 1, i)) if right_side_child?(r, i) end applicator end # Implements atcoder::lazy_segtree.get(index). def [](index : Int) index += @n_leaves @height.downto(1) { |j| propagate(ancestor(index, j)) } @segments[index].not_nil! end # Implements atcoder::lazy_segtree.prod(left, right). def [](range : Range) l = (range.begin || 0) + @n_leaves r = (range.exclusive? ? (range.end || @n_leaves) : (range.end || @n_leaves - 1) + 1) + @n_leaves @height.downto(1) do |i| propagate(ancestor(l, i)) if right_side_child?(l, i) propagate(ancestor(r - 1, i)) if right_side_child?(r, i) end sml, smr = nil.as(S | Nil), nil.as(S | Nil) while l < r if l.odd? sml = operate(sml, @segments[l]) l += 1 end if r.odd? r -= 1 smr = operate(@segments[r], smr) end l >>= 1 r >>= 1 end operate(sml, smr).not_nil! end # Implements atcoder::lazy_segtree.all_prod(). def all_prod self[0...@n] end # Implements atcoder::lazy_segtree.max_right(left, g). def max_right(left, e : S | Nil = nil, & : S -> Bool) unless 0 <= left && left <= @n raise IndexError.new("{left: #{left}} must greater than or equal to 0 and less than or equal to {n: #{@n}}") end unless e.nil? return nil unless yield e end return @n if left == @n left += @n_leaves @height.downto(1) { |i| propagate(ancestor(left, i)) } sm = e loop do while left.even? left >>= 1 end res = operate(sm, @segments[left]) unless res.nil? || yield res while left < @n_leaves propagate(left) left = 2*left res = operate(sm, @segments[left]) if res.nil? || yield res sm = res left += 1 end end return left - @n_leaves end sm = operate(sm, @segments[left]) left += 1 ffs = left & -left break if ffs == left end @n end # Implements atcoder::lazy_segtree.min_left(right, g). def min_left(right, e : S | Nil = nil, & : S -> Bool) unless 0 <= right && right <= @n raise IndexError.new("{right: #{right}} must greater than or equal to 0 and less than or equal to {n: #{@n}}") end unless e.nil? return nil unless yield e end return 0 if right == 0 right += @n_leaves @height.downto(1) { |i| propagate(ancestor(right - 1, i)) } sm = e loop do right -= 1 while right > 1 && right.odd? right >>= 1 end res = operate(@segments[right], sm) unless res.nil? || yield res while right < @n_leaves propagate(right) right = 2*right + 1 res = operate(@segments[right], sm) if res.nil? || yield res sm = res right -= 1 end end return right + 1 - @n_leaves end sm = operate(@segments[right], sm) ffs = right & -right break if ffs == right end 0 end @[AlwaysInline] private def operate(a : S | Nil, b : S | Nil) if a.nil? b elsif b.nil? a else @operator.call(a, b) end end @[AlwaysInline] private def apply(f : F | Nil, x : S | Nil) if f.nil? x elsif x.nil? nil else @application.call(f, x) end end @[AlwaysInline] private def compose(a : F | Nil, b : F | Nil) if a.nil? b elsif b.nil? a else @composition.call(a, b) end end @[AlwaysInline] private def refresh(node : Int) child1 = 2*node child2 = 2*node + 1 @segments[node] = operate(@segments[child1], @segments[child2]) end @[AlwaysInline] private def all_apply(node, applicator : F | Nil) @segments[node] = apply(applicator, @segments[node]) unless leaf?(node) @applicators[node] = compose(applicator, @applicators[node]) end end @[AlwaysInline] private def propagate(node : Int) child1 = 2*node child2 = 2*node + 1 all_apply(child1, @applicators[node]) all_apply(child2, @applicators[node]) @applicators[node] = nil end @[AlwaysInline] private def right_side_child?(child, n_gens_ago) ((child >> n_gens_ago) << n_gens_ago) != child end @[AlwaysInline] private def ancestor(node, n_gens_ago) node >> n_gens_ago end @[AlwaysInline] private def leaf?(node) node >= @n_leaves end @[AlwaysInline] private def log2_ceil(n : Int32) : Int32 sizeof(Int32)*8 - (n - 1).leading_zeros_count end end end # ac-library.cr by hakatashi https://github.com/google/ac-library.cr # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require "./prime.cr" # ac-library.cr by hakatashi https://github.com/google/ac-library.cr # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require "./math.cr" module AtCoder # Implements [Ruby's Prime library](https://ruby-doc.com/stdlib/libdoc/prime/rdoc/Prime.html). # # ``` # AtCoder::Prime.first(7) # => [2, 3, 5, 7, 11, 13, 17] # ``` module Prime extend self include Enumerable(Int64) @@primes = [ 2_i64, 3_i64, 5_i64, 7_i64, 11_i64, 13_i64, 17_i64, 19_i64, 23_i64, 29_i64, 31_i64, 37_i64, 41_i64, 43_i64, 47_i64, 53_i64, 59_i64, 61_i64, 67_i64, 71_i64, 73_i64, 79_i64, 83_i64, 89_i64, 97_i64, 101_i64, ] def each(&) index = 0 loop do yield get_nth_prime(index) index += 1 end end def prime_division(value : Int) raise DivisionByZeroError.new if value == 0 int = typeof(value) factors = [] of Tuple(typeof(value), typeof(value)) if value < 0 value = value.abs factors << {int.new(-1), int.new(1)} end until prime?(value) || value == 1 factor = value until prime?(factor) factor = find_factor(factor) end count = 0 while value % factor == 0 value //= factor count += 1 end factors << {int.new(factor), int.new(count)} end if value > 1 factors << {value, int.new(1)} end factors.sort_by! { |(factor, _)| factor } end private def find_factor(n : Int) # Factor of even numbers cannot be discovered by Pollard's Rho with f(x) = x^x+i if n.even? typeof(n).new(2) else pollard_rho(n).not_nil! end end # Get single factor by Pollard's Rho Algorithm private def pollard_rho(n : Int) typeof(n).new(1).upto(n) do |i| x = i y = pollard_random_f(x, n, i) loop do x = pollard_random_f(x, n, i) y = pollard_random_f(pollard_random_f(y, n, i), n, i) gcd = (x - y).gcd(n) if gcd == n break end if gcd != 1 return gcd end end end end @[AlwaysInline] private def pollard_random_f(n : Int, mod : Int, seed : Int) (AtCoder::Math.mul_mod(n, n, mod) + seed) % mod end private def extract_prime_division_base(prime_divisions_class : Array({T, T}).class) forall T T end def int_from_prime_division(prime_divisions : Array({Int, Int})) int_class = extract_prime_division_base(prime_divisions.class) prime_divisions.reduce(int_class.new(1)) { |i, (factor, exponent)| i * factor ** exponent } end def prime?(value : Int) # Obvious patterns return false if value < 2 return true if value <= 3 return false if value.even? return true if value < 9 if value < 0xffff return false unless typeof(value).new(30).gcd(value % 30) == 1 7.step(by: 30, to: value) do |base| break if base * base > value if {0, 4, 6, 10, 12, 16, 22, 24}.any? { |i| value % (base + i) == 0 } return false end end return true end miller_rabin(value.to_i64) end private def miller_rabin(value) d = value - 1 s = 0_i64 until d.odd? d >>= 1 s += 1 end miller_rabin_bases(value).each do |base| next if base == value x = AtCoder::Math.pow_mod(base.to_i64, d, value) next if x == 1 || x == value - 1 is_composite = s.times.all? do x = AtCoder::Math.mul_mod(x, x, value) x != value - 1 end return false if is_composite end true end # We can reduce time complexity of Miller-Rabin tests by testing against # predefined bases which is enough to test against primarity in the given range. # https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test # ameba:disable Metrics/CyclomaticComplexity private def miller_rabin_bases(value) case when value < 1_373_653_i64 [2, 3] when value < 9_080_191_i64 [31, 73] when value < 25_326_001_i64 [2, 3, 5] when value < 3_215_031_751_i64 [2, 3, 5, 7] when value < 4_759_123_141_i64 [2, 7, 61] when value < 1_122_004_669_633_i64 [2, 13, 23, 1662803] when value < 2_152_302_898_747_i64 [2, 3, 5, 7, 11] when value < 3_474_749_660_383_i64 [2, 3, 5, 7, 11, 13] when value < 341_550_071_728_321_i64 [2, 3, 5, 7, 11, 13, 17] when value < 3_825_123_056_546_413_051_i64 [2, 3, 5, 7, 11, 13, 17, 19, 23] else [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37] end end private def get_nth_prime(n) while @@primes.size <= n generate_primes end @@primes[n] end # Doubles the size of the cached prime array and performs the # Sieve of Eratosthenes on it. private def generate_primes new_primes_size = @@primes.size < 1_000_000 ? @@primes.size : 1_000_000 new_primes = Array(Int64).new(new_primes_size) { |i| @@primes.last + (i + 1) * 2 } new_primes_max = new_primes.last @@primes.each do |prime| next if prime == 2 break if prime * prime > new_primes_max # Here I use the technique of the Sieve of Sundaram. We can # only test against the odd multiple of the given prime. # min_composite is the minimum number that is greater than # the last confirmed prime, and is an odd multiple of # the given prime. min_multiple = ((@@primes.last // prime + 1) // 2 * 2 + 1) * prime min_multiple.step(by: prime * 2, to: new_primes_max) do |multiple| index = new_primes_size - (new_primes_max - multiple) // 2 - 1 new_primes[index] = 0_i64 end end @@primes.concat(new_primes.reject(0_i64)) end private struct EachDivisor(T) include Enumerable(T) def initialize(@exponential_factors : Array(Array(T))) end def each(&) Indexable.each_cartesian(@exponential_factors) do |factors| yield factors.reduce { |a, b| a * b } end end end # Returns an enumerator that iterates through the all positive divisors of # the given number. **The order is not guaranteed.** # Not in the original Ruby's Prime library. # # ``` # AtCoder::Prime.each_divisor(20) do |n| # puts n # end # => Puts 1, 2, 4, 5, 10, and 20 # # AtCoder::Prime.each_divisor(10).map { |n| 1.0 / n }.to_a # => [1.0, 0.5, 0.2, 0.1] # ``` def each_divisor(value : Int) raise ArgumentError.new unless value > 0 factors = prime_division(value) if value == 1 exponential_factors = [[value]] else exponential_factors = factors.map do |(factor, count)| cnt = typeof(value).zero + 1 Array(typeof(value)).new(count + 1) do |i| cnt_copy = cnt if i < count cnt *= factor end cnt_copy end end end EachDivisor(typeof(value)).new(exponential_factors) end # :ditto: def each_divisor(value : T, &block : T ->) each_divisor(value).each(&block) end end end struct Int def prime? AtCoder::Prime.prime?(self) end end module AtCoder # Implements [ACL's Math library](https://atcoder.github.io/ac-library/master/document_en/math.html) module Math def self.extended_gcd(a, b) zero = a.class.zero one = zero + 1 last_remainder, remainder = a.abs, b.abs x, last_x, y, last_y = zero, one, one, zero while remainder != 0 quotient, new_remainder = last_remainder.divmod(remainder) last_remainder, remainder = remainder, new_remainder x, last_x = last_x - quotient * x, x y, last_y = last_y - quotient * y, y end return last_remainder, last_x * (a < 0 ? -1 : 1) end # Implements atcoder::inv_mod(value, modulo). def self.inv_mod(value, modulo) gcd, inv = extended_gcd(value, modulo) if gcd != 1 raise ArgumentError.new("#{value} and #{modulo} are not coprime") end inv % modulo end # Simplified AtCoder::Math.pow_mod with support of Int64 def self.pow_mod(base, exponent, modulo) if exponent == 0 return base.class.zero + 1 end if base == 0 return base end b = exponent > 0 ? base : inv_mod(base, modulo) e = exponent.abs ret = 1_i64 while e > 0 if e % 2 == 1 ret = mul_mod(ret, b, modulo) end b = mul_mod(b, b, modulo) e //= 2 end ret end # Caluculates a * b % mod without overflow detection @[AlwaysInline] def self.mul_mod(a : Int64, b : Int64, mod : Int64) if mod < Int32::MAX return a * b % mod end # 31-bit width a_high = (a >> 32).to_u64 # 32-bit width a_low = (a & 0xFFFFFFFF).to_u64 # 31-bit width b_high = (b >> 32).to_u64 # 32-bit width b_low = (b & 0xFFFFFFFF).to_u64 # 31-bit + 32-bit + 1-bit = 64-bit c = a_high * b_low + b_high * a_low c_high = c >> 32 c_low = c & 0xFFFFFFFF # 31-bit + 31-bit res_high = a_high * b_high + c_high # 32-bit + 32-bit res_low = a_low * b_low res_low_high = res_low >> 32 res_low_low = res_low & 0xFFFFFFFF # Overflow if res_low_high + c_low >= 0x100000000 res_high += 1 end res_low = (((res_low_high + c_low) & 0xFFFFFFFF) << 32) | res_low_low (((res_high.to_i128 << 64) | res_low) % mod).to_i64 end @[AlwaysInline] def self.mul_mod(a, b, mod) typeof(mod).new(a.to_i64 * b % mod) end # Implements atcoder::crt(remainders, modulos). def self.crt(remainders, modulos) raise ArgumentError.new unless remainders.size == modulos.size total_modulo = 1_i64 answer = 0_i64 remainders.zip(modulos).each do |(remainder, modulo)| gcd, p = extended_gcd(total_modulo, modulo) if (remainder - answer) % gcd != 0 return 0_i64, 0_i64 end tmp = (remainder - answer) // gcd * p % (modulo // gcd) answer += total_modulo * tmp total_modulo *= modulo // gcd end return answer % total_modulo, total_modulo end # Implements atcoder::floor_sum(n, m, a, b). def self.floor_sum(n, m, a, b) n, m, a, b = n.to_i64, m.to_i64, a.to_i64, b.to_i64 res = 0_i64 if a < 0 a2 = a % m res -= n * (n - 1) // 2 * ((a2 - a) // m) a = a2 end if b < 0 b2 = b % m res -= n * ((b2 - b) // m) b = b2 end res + floor_sum_unsigned(n, m, a, b) end private def self.floor_sum_unsigned(n, m, a, b) res = 0_i64 loop do if a >= m res += n * (n - 1) // 2 * (a // m) a = a % m end if b >= m res += n * (b // m) b = b % m end y_max = a * n + b break if y_max < m n = y_max // m b = y_max % m m, a = a, m end res end # Returns `a * b > target`, without concern of overflows. def self.product_greater_than(a : Int, b : Int, target : Int) target // b < a end def self.get_primitive_root(p : Int) return 1_i64 if p == 2 n = p - 1 factors = AtCoder::Prime.prime_division(n) (2_i64..p.to_i64).each do |g| ok = true factors.each do |(factor, _)| if pow_mod(g, n // factor, p) == 1 ok = false break end end if ok return g end end raise ArgumentError.new end end end # ac-library.cr by hakatashi https://github.com/google/ac-library.cr # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. module AtCoder # Implements [atcoder::mf_graph](https://atcoder.github.io/ac-library/master/document_en/maxflow.html). # `Cap` is always `Int64`. # # ``` # mf = AtCoder::MaxFlow.new(3) # mf.add_edge(0, 1, 3) # mf.add_edge(1, 2, 1) # mf.add_edge(0, 2, 2) # mf.flow(0, 2) # => 3 # ``` class MaxFlow class Edge getter to : Int64 getter reverse_index : Int64 property capacity : Int64 def initialize(@to, @capacity, @reverse_index) end end # Number of nodes getter size : Int64 # Adjacency list getter adjacencies : Array(Array(Edge)) getter depths : Array(Int64) # Number of visited adjacencies for each nodes getter visit_counts : Array(Int64) def initialize(@size) @adjacencies = Array(Array(Edge)).new(@size) { [] of Edge } @depths = Array(Int64).new(@size, -1_i64) @visit_counts = Array(Int64).new(@size, 0_i64) end # Implements atcoder::mf_graph.add_edge(from, to, capacity). def add_edge(from, to, capacity) from_index = @adjacencies[from].size.to_i64 to_index = @adjacencies[to].size.to_i64 @adjacencies[from] << Edge.new(to.to_i64, capacity.to_i64, to_index) @adjacencies[to] << Edge.new(from.to_i64, 0_i64, from_index) end # Implements atcoder::mf_graph.flow(start, target). def flow(start, target) flow = 0_i64 loop do bfs(start) if @depths[target] < 0 return flow end @visit_counts.fill(0_i64) while (flowed = dfs(start, target, Int64::MAX)) > 0 flow += flowed end end end # FIXME: Unimplemented def min_cut raise NotImplementedError.new end # FIXME: Unimplemented def get_edge raise NotImplementedError.new end # FIXME: Unimplemented def edges raise NotImplementedError.new end # FIXME: Unimplemented def change_edge raise NotImplementedError.new end private def bfs(start) @depths.fill(-1_i64) queue = Deque(Int64).new @depths[start] = 0_i64 queue << start.to_i64 until queue.empty? node = queue.shift @adjacencies[node].each do |edge| if edge.capacity > 0 && @depths[edge.to] < 0 @depths[edge.to] = @depths[node] + 1 queue << edge.to end end end end private def dfs(node, target, flow) return flow if node == target edges = @adjacencies[node] while @visit_counts[node] < edges.size edge = edges[@visit_counts[node]] if edge.capacity > 0 && @depths[node] < @depths[edge.to] flowed = dfs(edge.to, target, min(flow, edge.capacity)) if flowed > 0 edge.capacity -= flowed @adjacencies[edge.to][edge.reverse_index].capacity += flowed return flowed end end @visit_counts[node] += 1 end 0_i64 end @[AlwaysInline] private def min(a, b) a > b ? b : a end end end # ac-library.cr by hakatashi https://github.com/google/ac-library.cr # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require "./graph.cr" module AtCoder # Implements [atcoder::mcf_graph](https://atcoder.github.io/ac-library/master/document_en/mincostflow.html). # # ``` # flow = AtCoder::MinCostFlow.new(5) # flow.add_edge(0, 1, 30, 3) # flow.add_edge(0, 2, 60, 9) # flow.add_edge(1, 2, 40, 5) # flow.add_edge(1, 3, 50, 7) # flow.add_edge(2, 3, 20, 8) # flow.add_edge(2, 4, 50, 6) # flow.add_edge(3, 4, 60, 7) # flow.flow(0, 4, 70) # => {70, 1080} # ``` class MinCostFlow private record EdgeInfo, capacity : Int64, cost : Int64 | Nil do def self.zero new(Int64::MAX, 0_i64) end def +(edge : EdgeInfo) from_cost = @cost to_cost = edge.cost if from_cost.nil? || to_cost.nil? return self.class.new(0_i64, nil) end self.class.new(min(@capacity, edge.capacity), from_cost + to_cost) end def >(edge : EdgeInfo) from_dist = dist to_dist = edge.dist return true if from_dist.nil? return false if to_dist.nil? from_dist > to_dist end def dist return nil if @capacity == 0 @cost end @[AlwaysInline] private def min(a, b) a > b ? b : a end end # Implements atcoder::mcf_graph g(n). def initialize(@size : Int64) @graph = AtCoder::DirectedGraph(Nil, EdgeInfo).new(@size) @dists = Array(Int64 | Nil).new(@size, 0_i64) @edges = [] of {Int64, Int64} end # Implements atcoder::mcf_graph.add_edge(from, to, capacity, cost). def add_edge(from, to, capacity, cost) @graph.add_edge(from, to, EdgeInfo.new(capacity.to_i64, cost.to_i64)) @graph.add_edge(to, from, EdgeInfo.new(0_i64, -cost.to_i64)) @edges << {from.to_i64, to.to_i64} end private def increment_edge_cost(from, to, cost_diff) edge = @graph.get_edge(from, to) @graph.update_edge(from, to, edge + EdgeInfo.new(edge.capacity, cost_diff)) end private def increment_edge_capacity(from, to, capacity_diff) edge = @graph.get_edge(from, to) @graph.update_edge(from, to, EdgeInfo.new(edge.capacity + capacity_diff, edge.cost)) end # Implements atcoder::mcf_graph.slope(start, target, flow_limit). # ameba:disable Metrics/CyclomaticComplexity def slope(start, target, flow_limit : Int | Nil = nil) raise ArgumentError.new("start and target cannot be the same") if start == target flow_points = [] of {Int64, Int64} current_cost = 0_i64 flowed_capacity = 0_i64 min_cost = 0_i64 until flowed_capacity == flow_limit nodes = @graph.dijkstra(start) target_dist = nodes[target][:dist] if target_dist.nil? || target_dist.capacity == 0 break end capacity = target_dist.capacity # Update edge capacities on the path from start to target last_node = target until last_node == start prev_node = nodes[last_node][:prev].not_nil! increment_edge_capacity(prev_node, last_node, -capacity) increment_edge_capacity(last_node, prev_node, capacity) last_node = prev_node end # Update edge costs @edges.each do |from, to| from_dist = nodes[from][:dist] to_dist = nodes[to][:dist] next if from_dist.nil? || to_dist.nil? next if from_dist.cost.nil? || to_dist.cost.nil? dist = to_dist.cost.not_nil! - from_dist.cost.not_nil! increment_edge_cost(from, to, -dist) increment_edge_cost(to, from, dist) end # Update distants nodes.each_with_index do |node, i| dist = node[:dist] if dist.nil? || @dists[i].nil? || dist.not_nil!.cost.nil? @dists[i] = nil else @dists[i] = @dists[i].not_nil! + dist.not_nil!.cost.not_nil! end end new_cost = @dists[target].not_nil! if flow_limit.nil? new_capacity = capacity else new_capacity = min(capacity, flow_limit - flowed_capacity) end if new_cost != current_cost if current_cost == 0 && flowed_capacity != 0 flow_points << {0_i64, 0_i64} end flow_points << {flowed_capacity, min_cost} end min_cost += new_cost * new_capacity flowed_capacity += new_capacity current_cost = new_cost end flow_points << {flowed_capacity, min_cost} flow_points end # Implements atcoder::mcf_graph.flow(start, target, flow_limit). def flow(start, target, flow_limit : Int | Nil = nil) flow_points = slope(start, target, flow_limit) flow_points.last end @[AlwaysInline] private def min(a, b) a > b ? b : a end delegate :size, to: @graph end end # ac-library.cr by hakatashi https://github.com/google/ac-library.cr # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require "./math.cr" module AtCoder # Implements [atcoder::static_modint](https://atcoder.github.io/ac-library/master/document_en/modint.html). # # ``` # AtCoder.static_modint(ModInt101, 101_i64) # alias Mint = AtCoder::ModInt101 # Mint.new(80_i64) + Mint.new(90_i64) # => 89 # ``` macro static_modint(name, modulo) module AtCoder # Implements atcoder::modint{{modulo}}. # # ``` # alias Mint = AtCoder::{{name}} # Mint.new(30_i64) // Mint.new(7_i64) # ``` struct {{name}} {% if modulo == 998_244_353_i64 %} MOD = 998_244_353_i64 M = 998_244_353_u32 R = 3_296_722_945_u32 MR = 998_244_351_u32 M2 = 932_051_910_u32 {% elsif modulo == 1_000_000_007_i64 %} MOD = 1_000_000_007_i64 M = 1_000_000_007_u32 R = 2_068_349_879_u32 MR = 2_226_617_417_u32 M2 = 582_344_008_u32 {% else %} MOD = {{modulo}} {% end %} def self.zero new end @@factorials = Array(self).new def self.factorial(n) if @@factorials.empty? @@factorials = Array(self).new(100_000_i64) @@factorials << self.new(1) end @@factorials.size.upto(n) do |i| @@factorials << @@factorials.last * i end @@factorials[n] end def self.permutation(n, k) raise ArgumentError.new("k cannot be greater than n") unless n >= k factorial(n) // factorial(n - k) end def self.combination(n, k) raise ArgumentError.new("k cannot be greater than n") unless n >= k permutation(n, k) // @@factorials[k] end def self.repeated_combination(n, k) combination(n + k - 1, k) end def - self.class.new(0) - self end def + self end def +(value) self + self.class.new(value) end def -(value) self - self.class.new(value) end def *(value) self * self.class.new(value) end def /(value) raise DivisionByZeroError.new if value == 0 self / self.class.new(value) end def /(value : self) raise DivisionByZeroError.new if value == 0 self * value.inv end def //(value) self / value end def <<(value) self * self.class.new(2) ** value end def abs value end def pred self - 1 end def succ self + 1 end def zero? value == 0 end def to_i64 value end def ==(other : self) value == other.value end def ==(other) value == other end def sqrt z = self.class.new(1_i64) until z ** ((MOD - 1) // 2) == MOD - 1 z += 1 end q = MOD - 1 m = 0 while q.even? q //= 2 m += 1 end c = z ** q t = self ** q r = self ** ((q + 1) // 2) m.downto(2) do |i| tmp = t ** (2 ** (i - 2)) if tmp != 1 r *= c t *= c ** 2 end c *= c end if r * r == self r.to_i64 * 2 <= MOD ? r : -r else nil end end # ac-library compatibility def pow(value) self ** value end def val self.to_i64 end # ModInt shouldn't be compared def <(value) raise NotImplementedError.new("<") end def <=(value) raise NotImplementedError.new("<=") end def >(value) raise NotImplementedError.new(">") end def >=(value) raise NotImplementedError.new(">=") end {% if modulo == 998_244_353_i64 || modulo == 1_000_000_007_i64 %} getter mgy : UInt32 # Initialize using montgomery representation def self.raw(mgy : UInt32) ret = new ret.mgy = mgy ret end def initialize @mgy = 0 end def initialize(value : Int) @mgy = reduce(((value % M).to_u64 + M) * M2) end def clone ret = self.class.new ret.mgy = @mgy ret end def +(value : self) ret = self.class.raw(@mgy) ret.mgy = (ret.mgy.to_i64 + value.mgy - 2*M).to_u32! if ret.mgy.to_i32! < 0 ret.mgy = (ret.mgy.to_u64 + 2*M).to_u32! end ret end def -(value : self) ret = self.class.raw(@mgy) ret.mgy = (ret.mgy.to_i64 - value.mgy).to_u32! if ret.mgy.to_i32! < 0 ret.mgy = (ret.mgy.to_u64 + 2*M).to_u32! end ret end def *(value : self) ret = self.class.raw(@mgy) ret.mgy = reduce(ret.mgy.to_u64 * value.mgy) ret end def **(value) if value == 0 return self.class.new(1) end if self.zero? self end b = value > 0 ? self : inv e = value.abs ret = self.class.new(1) while e > 0 if e.odd? ret *= b end b *= b e >>= 1 end ret end def inv g, x = AtCoder::Math.extended_gcd(value.to_i32, M.to_i32) self.class.new(x) end def to_s(io : IO) io << value end def inspect(io : IO) to_s(io) end def mgy=(v : UInt32) @mgy = v end @[AlwaysInline] def reduce(b : UInt64) : UInt32 ((b + (b.to_u32!.to_u64 * MR).to_u32!.to_u64 * M) >> 32).to_u32 end @[AlwaysInline] def value ret = reduce(@mgy.to_u64) ret >= M ? (ret - M).to_i64 : ret.to_i64 end {% else %} getter value : Int64 def initialize(@value : Int64 = 0_i64) @value %= MOD end def initialize(value) @value = value.to_i64 % MOD end def clone self.class.new(@value) end def inv g, x = AtCoder::Math.extended_gcd(@value, MOD) self.class.new(x) end def +(value : self) self.class.new(@value + value.to_i64) end def -(value : self) self.class.new(@value - value.to_i64) end def *(value : self) self.class.new(@value * value.to_i64) end def **(value) self.class.new(AtCoder::Math.pow_mod(@value, value.to_i64, MOD)) end delegate to_s, to: @value delegate inspect, to: @value {% end %} end end struct Int def +(value : AtCoder::{{name}}) value + self end def -(value : AtCoder::{{name}}) -value + self end def *(value : AtCoder::{{name}}) value * self end def //(value : AtCoder::{{name}}) value.inv * self end def /(value : AtCoder::{{name}}) self // value end def ==(value : AtCoder::{{name}}) value == self end end end end AtCoder.static_modint(ModInt1000000007, 1_000_000_007_i64) AtCoder.static_modint(ModInt998244353, 998_244_353_i64) AtCoder.static_modint(ModInt754974721, 754_974_721_i64) AtCoder.static_modint(ModInt167772161, 167_772_161_i64) AtCoder.static_modint(ModInt469762049, 469_762_049_i64) # ac-library.cr by hakatashi https://github.com/google/ac-library.cr # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # bench_red_black_tree.rb by Rubinius Project, (c) Rubinius Contributors # https://github.com/rubinius/rubinius-benchmark/blob/master/real_world/bench_red_black_tree.rb # Licensed under BSD License https://spdx.org/licenses/BSD-3-Clause.html # red_black_tree.cr by Crystal Language Project, (c) Manas Technology Solutions # https://github.com/crystal-lang/crystal/blob/master/samples/red_black_tree.cr # Licensed under MIT License https://mit-license.org module AtCoder class RedBlackTree class Node property :color property :key property! :left property! :right property! parent : self RED = :red BLACK = :black def initialize(@key : Int32, @color = RED) @left = @right = @parent = NilNode.instance end def black? color == BLACK end def red? color == RED end def nil_node? false end end class NilNode < Node def self.instance @@instance ||= RedBlackTree::NilNode.new end def initialize @key = 0 @color = BLACK @left = @right = @parent = self end def nil_node? true end end include Enumerable(Int32) property root : Node property :size def initialize @root = NilNode.instance @size = 0 end def insert(key) insert_node(Node.new(key)) end def insert_node(x) insert_helper(x) x.color = Node::RED while x != root && x.parent.color == Node::RED if x.parent == x.parent.parent.left y = x.parent.parent.right if !y.nil_node? && y.color == Node::RED x.parent.color = Node::BLACK y.color = Node::BLACK x.parent.parent.color = Node::RED x = x.parent.parent else if x == x.parent.right x = x.parent left_rotate(x) end x.parent.color = Node::BLACK x.parent.parent.color = Node::RED right_rotate(x.parent.parent) end else y = x.parent.parent.left if !y.nil_node? && y.color == Node::RED x.parent.color = Node::BLACK y.color = Node::BLACK x.parent.parent.color = Node::RED x = x.parent.parent else if x == x.parent.left x = x.parent right_rotate(x) end x.parent.color = Node::BLACK x.parent.parent.color = Node::RED left_rotate(x.parent.parent) end end end root.color = Node::BLACK end def delete_node(z) y = (z.left.nil_node? || z.right.nil_node?) ? z : successor(z) x = y.left.nil_node? ? y.right : y.left x.parent = y.parent if y.parent.nil_node? self.root = x else if y == y.parent.left y.parent.left = x else y.parent.right = x end end z.key = y.key if y != z if y.color == Node::BLACK delete_fixup(x) end self.size -= 1 y end def minimum_node(x = root) while !x.left.nil_node? x = x.left end x end def maximum_node(x = root) while !x.right.nil_node? x = x.right end x end def successor(x) if !x.right.nil_node? return minimum_node(x.right) end y = x.parent while !y.nil_node? && x == y.right x = y y = y.parent end y end def predecessor(x) if !x.left.nil_node? return maximum_node(x.left) end y = x.parent while !y.nil_node? && x == y.left x = y y = y.parent end y end def inorder_walk(x = root, &) # ameba:disable Lint/ShadowedArgument x = self.minimum_node while !x.nil_node? yield x.key x = successor(x) end end def each(x = root, &) inorder_walk(x) { |k| yield k } end def reverse_inorder_walk(x = root, &) # ameba:disable Lint/ShadowedArgument x = self.maximum_node while !x.nil_node? yield x.key x = predecessor(x) end end def reverse_each(x = root, &) reverse_inorder_walk(x) { |k| yield k } end def search(key, x = root) while !x.nil_node? && x.key != key x = (key < x.key) ? x.left : x.right end x end def lower_than(key, x = root) while !x.nil_node? && x.key != key tmp = (key < x.key) ? x.left : x.right if tmp.nil_node? return x end x = tmp end x end def empty? self.root.nil_node? end def black_height(x = root) height = 0 while !x.nil_node? x = x.left height += 1 if x.nil_node? || x.black? end height end private def left_rotate(x) raise "x.right is nil!" if x.right.nil_node? y = x.right x.right = y.left y.left.parent = x if !y.left.nil_node? y.parent = x.parent if x.parent.nil_node? self.root = y else if x == x.parent.left x.parent.left = y else x.parent.right = y end end y.left = x x.parent = y end private def right_rotate(x) raise "x.left is nil!" if x.left.nil_node? y = x.left x.left = y.right y.right.parent = x if !y.right.nil_node? y.parent = x.parent if x.parent.nil_node? self.root = y else if x == x.parent.left x.parent.left = y else x.parent.right = y end end y.right = x x.parent = y end private def insert_helper(z) y = NilNode.instance x = root while !x.nil_node? y = x x = (z.key < x.key) ? x.left : x.right end z.parent = y if y.nil_node? self.root = z else z.key < y.key ? y.left = z : y.right = z end self.size += 1 end # ameba:disable Metrics/CyclomaticComplexity private def delete_fixup(x) while x != root && x.color == Node::BLACK if x == x.parent.left w = x.parent.right if w.color == Node::RED w.color = Node::BLACK x.parent.color = Node::RED left_rotate(x.parent) w = x.parent.right end if w.left.color == Node::BLACK && w.right.color == Node::BLACK w.color = Node::RED x = x.parent else if w.right.color == Node::BLACK w.left.color = Node::BLACK w.color = Node::RED right_rotate(w) w = x.parent.right end w.color = x.parent.color x.parent.color = Node::BLACK w.right.color = Node::BLACK left_rotate(x.parent) x = root end else w = x.parent.left if w.color == Node::RED w.color = Node::BLACK x.parent.color = Node::RED right_rotate(x.parent) w = x.parent.left end if w.right.color == Node::BLACK && w.left.color == Node::BLACK w.color = Node::RED x = x.parent else if w.left.color == Node::BLACK w.right.color = Node::BLACK w.color = Node::RED left_rotate(w) w = x.parent.left end w.color = x.parent.color x.parent.color = Node::BLACK w.left.color = Node::BLACK right_rotate(x.parent) x = root end end end x.color = Node::BLACK end def min minimum_node.key end def max maximum_node.key end def delete(key) node = search(key) unless node.nil_node? delete_node(node) end end def has_key?(key) node = search(key) !node.nil_node? end def <<(x) insert(x) end end end # ac-library.cr by hakatashi https://github.com/google/ac-library.cr # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. module AtCoder # Implements [atcoder::scc_graph](https://atcoder.github.io/ac-library/master/document_en/scc.html). # # ``` # scc = AtCoder::SCC.new(3_i64) # scc.add_edge(0, 1) # scc.add_edge(1, 0) # scc.add_edge(2, 0) # scc.scc # => [Set{2}, Set{0, 1}] # ``` class SCC alias Adjacency = NamedTuple(in: Array(Int64), out: Array(Int64)) getter size : Int64 getter adjacencies : Array(Adjacency) def initialize(@size) @adjacencies = Array(Adjacency).new(@size) { {in: [] of Int64, out: [] of Int64} } @topological_order = Array(Int64).new(@size) @visit_counts = Array(Int64).new(@size, 0_i64) @visited = Set(Int64).new @stack = Deque(Int64).new @groups = Array(Set(Int64)).new end # Implements atcoder::scc_graph.add_edge(from, to). def add_edge(from, to) @adjacencies[from][:out] << to.to_i64 @adjacencies[to][:in] << from.to_i64 end private def dfs(start) @stack << start @visited << start until @stack.empty? node = @stack.last children = @adjacencies[node][:out] if @visit_counts[node] < children.size child = children[@visit_counts[node]] @visit_counts[node] += 1 unless @visited.includes?(child) @visited << child @stack << child end else @topological_order << node @stack.pop end end end private def reverse_dfs(start) @stack << start @visited << start group = Set{start} until @stack.empty? node = @stack.pop children = @adjacencies[node][:in] children.each do |child| unless @visited.includes?(child) @stack << child @visited << child group << child end end end @groups << group end # Implements atcoder::scc_graph.scc(). def scc @visited = Set(Int64).new @stack = Deque(Int64).new @visit_counts = Array(Int64).new(@size, 0_i64) @topological_order = Array(Int64).new(@size) @groups = Array(Set(Int64)).new @size.times do |node| unless @visited.includes?(node) dfs(node) end end @visited = Set(Int64).new @topological_order.reverse_each do |node| unless @visited.includes?(node) reverse_dfs(node) end end @groups end end end # ac-library.cr by hakatashi https://github.com/google/ac-library.cr # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. module AtCoder # Implements [atcoder::segtree](https://atcoder.github.io/ac-library/master/document_en/segtree.html). # # The identity element will be implicitly defined as nil, so you don't # have to manually define it. In the other words, you cannot include # nil into an element of the monoid. # # ``` # tree = AtCoder::SegTree.new((0...100).to_a) { |a, b| [a, b].min } # tree[10...50] # => 10 # ``` class SegTree(T) getter values : Array(T) @height : Int32 @n_leaves : Int32 def initialize(values : Array(T)) initialize(values) { |a, b| a > b ? a : b } end def initialize(@values : Array(T), &@operator : T, T -> T) @height = log2_ceil(@values.size) @n_leaves = 1 << @height @segments = Array(T | Nil).new(2 * @n_leaves, nil) # initialize segments values.each_with_index { |x, i| @segments[@n_leaves + i] = x.as(T | Nil) } (@n_leaves - 1).downto(1) { |i| refresh(i) } end @[AlwaysInline] private def operate(a : T | Nil, b : T | Nil) if a.nil? b elsif b.nil? a else @operator.call(a, b) end end # Implements atcoder::segtree.set(index, value) def []=(index : Int, value : T) @values[index] = value index += @n_leaves @segments[index] = value.as(T | Nil) (1..@height).each { |j| refresh(ancestor(index, j)) } end # Implements atcoder::segtree.get(index) def [](index : Int) @values[index] end # Implements atcoder::segtree.prod(l, r) def [](range : Range) l = (range.begin || 0) + @n_leaves r = (range.exclusive? ? (range.end || @n_leaves) : (range.end || @n_leaves - 1) + 1) + @n_leaves sml, smr = nil.as(T | Nil), nil.as(T | Nil) while l < r if l.odd? sml = operate(sml, @segments[l]) l += 1 end if r.odd? r -= 1 smr = operate(@segments[r], smr) end l >>= 1 r >>= 1 end operate(sml, smr).not_nil! end # compatibility with ac-library # Implements atcoder::segtree.set(index, value) # alias of `.[]=` def set(index : Int, value : T) self.[]=(index, value) end # Implements atcoder::segtree.get(index) # alias of `.[]` def get(index : Int) self.[](index) end # Implements atcoder::segtree.prod(left, right) def prod(left : Int, right : Int) self.[](left...right) end # Implements atcoder::segtree.all_prod(l, r) def all_prod @segments[1].not_nil! end # Implements atcoder::lazy_segtree.max_right(left, g). def max_right(left, e : T | Nil = nil, & : T -> Bool) unless 0 <= left && left <= @values.size raise IndexError.new("{left: #{left}} must greater than or equal to 0 and less than or equal to {n: #{@values.size}}") end unless e.nil? return nil unless yield e end return @values.size if left == @values.size left += @n_leaves sm = e loop do while left.even? left >>= 1 end res = operate(sm, @segments[left]) unless res.nil? || yield res while left < @n_leaves left = 2*left res = operate(sm, @segments[left]) if res.nil? || yield res sm = res left += 1 end end return left - @n_leaves end sm = operate(sm, @segments[left]) left += 1 ffs = left & -left break if ffs == left end @values.size end # Implements atcoder::lazy_segtree.min_left(right, g). def min_left(right, e : T | Nil = nil, & : T -> Bool) unless 0 <= right && right <= @values.size raise IndexError.new("{right: #{right}} must greater than or equal to 0 and less than or equal to {n: #{@values.size}}") end unless e.nil? return nil unless yield e end return 0 if right == 0 right += @n_leaves sm = e loop do right -= 1 while right > 1 && right.odd? right >>= 1 end res = operate(@segments[right], sm) unless res.nil? || yield res while right < @n_leaves right = 2*right + 1 res = operate(@segments[right], sm) if res.nil? || yield res sm = res right -= 1 end end return right + 1 - @n_leaves end sm = operate(@segments[right], sm) ffs = right & -right break if ffs == right end 0 end @[AlwaysInline] private def refresh(node : Int) child1 = 2*node child2 = 2*node + 1 @segments[node] = operate(@segments[child1], @segments[child2]) end @[AlwaysInline] private def ancestor(node, n_gens_ago) node >> n_gens_ago end @[AlwaysInline] private def log2_ceil(n : Int32) : Int32 sizeof(Int32)*8 - (n - 1).leading_zeros_count end @[AlwaysInline] private def log2_ceil(n : Int32) : Int32 sizeof(Int32)*8 - (n - 1).leading_zeros_count end end end # ac-library.cr by hakatashi https://github.com/google/ac-library.cr # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. module AtCoder class SkewHeap(T) @root : Node(T) | Nil @size : Int64 getter :size class Node(T) @left : Node(T) | Nil @right : Node(T) | Nil @value : T property :value, :left, :right def initialize(@left, @right, @value) end end def initialize initialize { |a, b| a <= b } end def initialize(&block : T, T -> Bool) @root = nil @size = 0_i64 @compare_proc = block end def meld(a : Node(T) | Nil, b : Node(T) | Nil) return b if a.nil? return a if b.nil? if @compare_proc.call(a.value, b.value) a, b = b, a end a.right = meld(a.right, b) a.left, a.right = a.right, a.left a end def push(value : T) @root = meld(@root, Node(T).new(nil, nil, value)) @size += 1 end def pop return nil if @root.nil? root = @root.not_nil! ret = root.value @root = meld(root.left, root.right) @size -= 1 ret end # Alias of `push` def <<(v : T) push(v) end def empty? @size == 0 end end end # ac-library.cr by hakatashi https://github.com/google/ac-library.cr # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. module AtCoder module String private SA_THRESHOLD_NAIVE = 10 private SA_THRESHOLD_DOUBLING = 40 private def self.sa_naive(s) n = s.size sa = (0...n).to_a.sort { |l, r| next 1 if l == r res = nil while l < n && r < n if s[l] != s[r] res = s[l] <=> s[r] break end l += 1 r += 1 end res ? res : (l == n ? -1 : 1) } sa end private def self.sa_doubling(s) n = s.size sa = (0...n).to_a rank = s.clone tmp = [0] * n k = 1 while k < n cmp = ->(x : Int32, y : Int32) { return rank[x] <=> rank[y] if rank[x] != rank[y] rx = x + k < n ? rank[x + k] : -1 ry = y + k < n ? rank[y + k] : -1 rx <=> ry } sa.sort! { |a, b| cmp.call(a, b) } tmp[sa[0]] = 0 (1...n).each do |i| tmp[sa[i]] = tmp[sa[i - 1]] + (cmp.call(sa[i - 1], sa[i]) == -1 ? 1 : 0) end tmp, rank = rank, tmp k *= 2 end sa end # ameba:disable Metrics/CyclomaticComplexity private def self.sa_is(s, upper) n = s.size case n when .==(0) return [] of Int32 when .==(1) return [0] when .==(2) return s[0] < s[1] ? [0, 1] : [1, 0] when .<(SA_THRESHOLD_NAIVE) return sa_naive(s) when .<(SA_THRESHOLD_DOUBLING) return sa_doubling(s) end sa = [0] * n ls = [false] * n (n - 2).downto(0) do |i| ls[i] = s[i] == s[i + 1] ? ls[i + 1] : s[i] < s[i + 1] end sum_l = [0] * (upper + 1) sum_s = [0] * (upper + 1) n.times do |i| if ls[i] sum_l[s[i] + 1] += 1 else sum_s[s[i]] += 1 end end (0..upper).each do |i| sum_s[i] += sum_l[i] sum_l[i + 1] += sum_s[i] if i < upper end induce = ->(lms : Array(Int32)) do sa = [-1] * n buffer = sum_s.clone lms.each do |d| next if d == n sa[buffer[s[d]]] = d buffer[s[d]] += 1 end buffer = sum_l.clone sa[buffer[s[n - 1]]] = n - 1 buffer[s[n - 1]] += 1 n.times do |i| v = sa[i] if v >= 1 && !ls[v - 1] sa[buffer[s[v - 1]]] = v - 1 buffer[s[v - 1]] += 1 end end buffer = sum_l.clone (n - 1).downto(0) do |i| v = sa[i] if v >= 1 && ls[v - 1] buffer[s[v - 1] + 1] -= 1 sa[buffer[s[v - 1] + 1]] = v - 1 end end end lms_map = [-1] * (n + 1) m = 0 (1...n).each do |i| if !ls[i - 1] && ls[i] lms_map[i] = m m += 1 end end lms = Array(Int32).new(m) (1...n).each do |i| if !ls[i - 1] && ls[i] lms << i end end induce.call(lms) return sa if m == 0 sorted_lms = Array(Int32).new(m) sa.each do |v| sorted_lms << v if lms_map[v] != -1 end rec_s = [0] * m rec_upper = 0 rec_s[lms_map[sorted_lms[0]]] = 0 (1...m).each do |i| l = sorted_lms[i - 1] r = sorted_lms[i] end_l = (lms_map[l] + 1 < m) ? lms[lms_map[l] + 1] : n end_r = (lms_map[r] + 1 < m) ? lms[lms_map[r] + 1] : n same = true if end_l - l != end_r - r same = false else while l < end_l break if s[l] != s[r] l += 1 r += 1 end same = false if l == n || s[l] != s[r] end rec_upper += 1 unless same rec_s[lms_map[sorted_lms[i]]] = rec_upper end rec_sa = sa_is(rec_s, rec_upper) m.times do |i| sorted_lms[i] = lms[rec_sa[i]] end induce.call(sorted_lms) sa end # returns suffix array in O(n + upper) def self.suffix_array(sequence : Indexable(Int32), upper) sa_is(sequence, upper) end # returns suffix array in O(n log(n)) def self.suffix_array(sequence : Indexable) n = sequence.size indices = (0...n).to_a.sort { |l, r| sequence[l] <=> sequence[r] } s2 = [0] * n now = 0 n.times do |i| now += 1 if i > 0 && sequence[indices[i - 1]] != sequence[indices[i]] s2[indices[i]] = now end upper = now sa_is(s2, upper) end # returns suffix array in O(n) def self.suffix_array(sequence : ::String) sa_is(sequence.bytes.map(&.to_i32), 255) end # returns lcp array in O(n) def self.lcp_array(sequence, sa) n = sequence.size rank = [0] * n sa.each_with_index { |e, i| rank[e] = i } lcp = [0] * (n - 1) h = 0 n.times do |i| h -= 1 if h > 0 next if rank[i] == 0 j = sa[rank[i] - 1] while j + h < n && i + h < n break if sequence[j + h] != sequence[i + h] h += 1 end lcp[rank[i] - 1] = h end lcp end # returns z array def self.z_algorithm(sequence) n = sequence.size return [] of Int32 if n == 0 z = [0] * n i, j = 1, 0 while i < n z[i] = (j + z[j] <= i) ? 0 : (j + z[j] - i < z[i - j] ? j + z[j] - i : z[i - j]) while i + z[i] < n && sequence[z[i]] == sequence[i + z[i]] z[i] += 1 end j = i if j + z[j] < i + z[i] i += 1 end z[0] = n z end end end # ac-library.cr by hakatashi https://github.com/google/ac-library.cr # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require "./scc.cr" module AtCoder # Implements [atcoder::two_sat](https://atcoder.github.io/ac-library/master/document_en/twosat.html) # # ``` # twosat = AtCoder::TwoSat.new(2_i64) # twosat.add_clause(0, true, 1, false) # twosat.add_clause(1, true, 0, false) # twosat.add_clause(0, false, 1, false) # twosat.satisfiable? # => true # twosat.answer # => [false, false] # ``` class TwoSat getter size : Int64 class NotSatisfiableError < Exception def initialize super("The formula is not satisfiable") end end def initialize(@size) @scc = AtCoder::SCC.new(@size * 2) @solved = false @satisfiable = false @group_list = Array(Int64).new(@size * 2, 0_i64) end @[AlwaysInline] private def var(i, f) if f i.to_i64 else i.to_i64 + @size end end # Implements atcoder::two_sat.add_clause(i, f, j, g). def add_clause(i, f, j, g) @scc.add_edge(var(i, !f), var(j, g)) @scc.add_edge(var(j, !g), var(i, f)) end # Implements atcoder::two_sat.satisfiable(). def satisfiable? @satisfiable = false groups = @scc.scc @group_list = Array(Int64).new(@size * 2, 0_i64) groups.each_with_index do |group, i| group.each do |item| @group_list[item] = i.to_i64 end end @size.times do |i| if @group_list[i] == @group_list[i + @size] return false end end @satisfiable = true end # Implements atcoder::two_sat.answer(). # # This method will raise `NotSatisfiableError` if it's not satisfiable. def answer unless @satisfiable raise NotSatisfiableError.new end Array(Bool).new(@size) do |i| @group_list.not_nil![i] > @group_list.not_nil![i + @size] end end end end