結果
問題 | No.470 Inverse S+T Problem |
ユーザー | yuruhiya |
提出日時 | 2021-07-29 13:08:54 |
言語 | Crystal (1.11.2) |
結果 |
AC
|
実行時間 | 11 ms / 2,000 ms |
コード長 | 11,605 bytes |
コンパイル時間 | 14,263 ms |
コンパイル使用メモリ | 304,824 KB |
実行使用メモリ | 7,680 KB |
最終ジャッジ日時 | 2024-06-01 23:08:37 |
合計ジャッジ時間 | 15,345 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
6,812 KB |
testcase_01 | AC | 3 ms
6,816 KB |
testcase_02 | AC | 2 ms
6,820 KB |
testcase_03 | AC | 3 ms
6,944 KB |
testcase_04 | AC | 3 ms
6,944 KB |
testcase_05 | AC | 2 ms
6,944 KB |
testcase_06 | AC | 11 ms
7,680 KB |
testcase_07 | AC | 10 ms
7,680 KB |
testcase_08 | AC | 10 ms
7,680 KB |
testcase_09 | AC | 2 ms
6,940 KB |
testcase_10 | AC | 2 ms
6,940 KB |
testcase_11 | AC | 3 ms
6,940 KB |
testcase_12 | AC | 3 ms
6,940 KB |
testcase_13 | AC | 3 ms
6,944 KB |
testcase_14 | AC | 2 ms
6,940 KB |
testcase_15 | AC | 3 ms
6,940 KB |
testcase_16 | AC | 3 ms
6,944 KB |
testcase_17 | AC | 3 ms
6,940 KB |
testcase_18 | AC | 2 ms
6,940 KB |
testcase_19 | AC | 3 ms
6,944 KB |
testcase_20 | AC | 2 ms
6,944 KB |
testcase_21 | AC | 3 ms
6,944 KB |
testcase_22 | AC | 3 ms
6,944 KB |
testcase_23 | AC | 3 ms
6,944 KB |
testcase_24 | AC | 3 ms
6,940 KB |
testcase_25 | AC | 3 ms
6,940 KB |
testcase_26 | AC | 3 ms
6,940 KB |
testcase_27 | AC | 3 ms
6,944 KB |
testcase_28 | AC | 4 ms
6,940 KB |
testcase_29 | AC | 3 ms
6,940 KB |
testcase_30 | AC | 3 ms
6,944 KB |
コンパイルメッセージ
In Main.cr:418:17 418 | chars2 = chars1.product(chars1).map { |c1, c2| "#{c1}#{c2}" } ^------ Warning: Deprecated Array(Char)#product. Use `Indexable#cartesian_product(*others : Indexable)` instead A total of 1 warnings were found.
ソースコード
# require "/scanner" # ### Specifications # # ```plain # Inside input macro | Expanded code # ----------------------------------------------+--------------------------------------- # Uppercase string: Int32, Int64, Float64, etc. | {}.new(Scanner.s) # s | Scanner.s # c | Scanner.c # Other lowercase string: i, i64, f, etc. | Scanner.s.to_{} # operator[]: type[size] | Array.new(input(size)) { input(type) } # Tuple literal: {t1, t2, t3} | {input(t1), input(t2), input(t3)} # Array literal: [t1, t2, t3] | [input(t1), input(t2), input(t3)] # Range literal: t1..t2 | input(t1)..input(t2) # If: cond ? t1 : t2 | cond ? input(t1) : input(t2) # Assign: target = value | target = input(value) # ``` # # ### Examples # # Input: # ```plain # 5 3 # foo bar # 1 2 3 4 5 # ``` # ``` # n, m = input(Int32, Int64) # => {5, 10i64} # input(String, Char[m]) # => {"foo", ['b', 'a', 'r']} # input(Int32[n]) # => [1, 2, 3, 4, 5] # ``` # ``` # n, m = input(i, i64) # => {5, 10i64} # input(s, c[m]) # => {"foo", ['b', 'a', 'r']} # input(i[n]) # => [1, 2, 3, 4, 5] # ``` # # Input: # ```plain # 2 3 # 1 2 3 # 4 5 6 # ``` # # ``` # h, w = input(i, i) # => {2, 3} # input(i[h, w]) # => [[1, 2, 3], [4, 5, 6]] # ``` # ``` # input(i[i][i]) # => [[1, 2, 3], [4, 5, 6]] # ``` # # Input: # ```plain # 5 3 # 3 1 4 2 5 # 1 2 # 2 3 # 3 1 # ``` # ``` # n, m = input(i, i) # => {5, 3} # input(i.pred[n]) # => [2, 0, 3, 1, 4] # input({i - 1, i - 1}[m]) # => [{0, 1}, {1, 2}, {2, 0}] # ``` # # Input: # ```plain # 3 # 1 2 # 2 2 # 3 2 # ``` # ``` # input({tmp = i, tmp == 1 ? i : i.pred}[i]) # => [{1, 2}, {2, 1}, {3, 1}] # ``` # # Input: # ```plain # 3 # 1 2 # 2 3 # 3 1 # ``` # ``` # n = input(i) # input_column({Int32, Int32}, n) # => {[1, 2, 3], [2, 3, 1]} # ``` class Scanner private def self.skip_to_not_space peek = STDIN.peek not_space = peek.index { |x| x != 32 && x != 10 } || peek.size STDIN.skip(not_space) end def self.c skip_to_not_space STDIN.read_char.not_nil! end def self.s skip_to_not_space peek = STDIN.peek if index = peek.index { |x| x == 32 || x == 10 } STDIN.skip(index + 1) return String.new(peek[0, index]) end String.build do |buffer| loop do buffer.write peek STDIN.skip(peek.size) peek = STDIN.peek break if peek.empty? if index = peek.index { |x| x == 32 || x == 10 } buffer.write peek[0, index] STDIN.skip(index) break end end end end end macro internal_input(type, else_ast) {% if Scanner.class.has_method?(type.id) %} Scanner.{{type.id}} {% elsif type.stringify == "String" %} Scanner.s {% elsif type.stringify == "Char" %} Scanner.c {% elsif type.stringify =~ /[A-Z][a-z0-9_]*/ %} {{type.id}}.new(Scanner.s) {% elsif String.has_method?("to_#{type}".id) %} Scanner.s.to_{{type.id}} {% else %} {{else_ast}} {% end %} end macro internal_input_array(type, args) {% for i in 0...args.size %} %size{i} = input({{args[i]}}) {% end %} {% begin %} {% for i in 0...args.size %} Array.new(%size{i}) { {% end %} input({{type.id}}) {% for i in 0...args.size %} } {% end %} {% end %} end macro input(type) {% if type.is_a?(Call) %} {% if type.receiver.is_a?(Nop) %} internal_input( {{type.name}}, {{type.name}}( {% for argument in type.args %} input({{argument}}), {% end %} ) ) {% elsif type.name.stringify == "[]" %} internal_input_array({{type.receiver}}, {{type.args}}) {% else %} input({{type.receiver}}).{{type.name.id}}( {% for argument in type.args %} input({{argument}}), {% end %} ) {{type.block}} {% end %} {% elsif type.is_a?(TupleLiteral) %} { {% for i in 0...type.size %} input({{type[i]}}), {% end %} } {% elsif type.is_a?(ArrayLiteral) %} [ {% for i in 0...type.size %} input({{type[i]}}), {% end %} ] {% elsif type.is_a?(RangeLiteral) %} Range.new(input({{type.begin}}), input({{type.end}}), {{type.excludes_end?}}) {% elsif type.is_a?(If) %} {{type.cond}} ? input({{type.then}}) : input({{type.else}}) {% elsif type.is_a?(Assign) %} {{type.target}} = input({{type.value}}) {% else %} internal_input({{type.id}}, {{type.id}}) {% end %} end macro input(*types) { {% for type in types %} input({{type}}), {% end %} } end macro input_column(types, size) {% for type, i in types %} %array{i} = Array({{type}}).new({{size}}) {% end %} {{size}}.times do {% for type, i in types %} %array{i} << input({{type}}) {% end %} end { {% for type, i in types %} %array{i}, {% end %} } end # require "atcoder/TwoSat" # ac-library.cr by hakatashi https://github.com/google/ac-library.cr # # Copyright 2021 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" # ac-library.cr by hakatashi https://github.com/google/ac-library.cr # # Copyright 2021 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 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 n = input(Int64) s = input(String[n]) chars1 = ('a'..'z').to_a + ('A'..'Z').to_a chars2 = chars1.product(chars1).map { |c1, c2| "#{c1}#{c2}" } index1 = chars1.zip(0..).to_h index2 = chars2.zip(0..).to_h if n > 52 puts "Impossible" exit end two_sat = AtCoder::TwoSat.new(n) (0...n).each do |i| (i + 1...n).each do |j| if s[i][0] == s[j][0] || s[i][1..2] == s[j][1..2] two_sat.add_clause(i, false, j, false) end if s[i][0] == s[j][2] || s[i][1..2] == s[j][0..1] two_sat.add_clause(i, false, j, true) end if s[i][2] == s[j][0] || s[i][0..1] == s[j][1..2] two_sat.add_clause(i, true, j, false) end if s[i][2] == s[j][2] || s[i][0..1] == s[j][0..1] two_sat.add_clause(i, true, j, true) end end end if two_sat.satisfiable? two_sat.answer.each_with_index do |f, i| if f puts [s[i][0], s[i][1..2]].join(' ') else puts [s[i][0..1], s[i][2]].join(' ') end end else puts "Impossible" end