はじめに
AtCoder さん、ありがとうございます。
C - Dice Sum
動的計画法を応用して解きました。
Ruby
n, m, k = gets.split.map(&:to_i)
MOD = 998244353
dp = Hash.new(0)
dp[0] = 1
n.times do |i|
dp2 = Hash.new(0)
(1..m).each do |x|
dp.keys.each do |key|
if key + x <= k
dp2[key + x] += dp[key]
dp2[key + x] %= MOD
end
end
end
dp = dp2
end
puts dp.values.sum % MOD
動的計画法では、配列をコピーしたりしますが、Hash#keys
でコピーしている様な感じです。
crystal
n, m, k = read_line.split.map(&.to_i)
MOD = 998244353
dp = Hash(Int32, Int64).new(0)
dp[0] = 1
n.times do |i|
dp2 = Hash(Int32, Int64).new(0)
(1..m).each do |x|
dp.keys.each do |key|
if key + x <= k
dp2[key + x] += dp[key]
dp2[key + x] %= MOD
end
end
end
dp = dp2
end
puts dp.values.sum % MOD
crystal
ではHash
を使用する際、変数の型を指定する必要があります。
ここでは、Int32
を越える可能性がありますので、Int64
を指定しています。
Ruby | crystal | |
---|---|---|
コード長(Byte) | 319 | 358 |
実行時間(ms) | 706 | 179 |
D - Range Count Query
二分探索を応用して解きました。
Ruby
n = gets.to_i
a = gets.split.map(&:to_i)
h = Hash.new{ |h, k| h[k] = [] }
a.each_with_index do |e, i|
h[e] << i + 1
end
q = gets.to_i
q.times do
l, r, x = gets.split.map(&:to_i)
if h.has_key?(x)
ss = h[x].bsearch_index{ |e| l <= e } || h[x].size
se = h[x].bsearch_index{ |e| r < e } || h[x].size
puts se - ss
else
puts 0
end
end
ここは、範囲を超えた場合のnil
対策です。
nilガード
ss = h[x].bsearch_index{ |e| l <= e } || h[x].size
crystal
n = read_line.to_i
a = read_line.split.map(&.to_i)
h = Hash(Int32, Array(Int32)).new{ |h, k| h[k] = [] of Int32 }
a.each_with_index do |e, i|
h[e] << i + 1
end
q = read_line.to_i
q.times do
l, r, x = read_line.split.map(&.to_i)
if h.has_key?(x)
ss = h[x].bsearch_index{ |e| l <= e } || h[x].size
se = h[x].bsearch_index{ |e| r < e } || h[x].size
puts se - ss
else
puts 0
end
end
Ruby
でハッシュの値に配列を使用する場合の定番の書き方があります。
Hash
h = Hash.new{ |h, k| h[k] = [] }
crystal
での書き方がよく分からないのですが、ごてごてしいです。
Hash
h = Hash(Int32, Array(Int32)).new{ |h, k| h[k] = [] of Int32 }
Ruby | crystal | |
---|---|---|
コード長(Byte) | 370 | 423 |
実行時間(ms) | 665 | 164 |
まとめ
crystal
はnil安全として静的な型チェックが入りますので、それを意識してコーディングする必要があります。