LoginSignup
0
0

More than 3 years have passed since last update.

【AtCoder】ABC085C - Otoshidama

Posted at

これは何?

AtCoderという競技プログラミングサイトの練習問題についての私の解答です。
入門者用の練習問題なのでそれほど難しくはないはずなんですが、自力では解けなかったので記録として載せます。

問題はこちら。
https://atcoder.jp/contests/abs/tasks/abc085_c

解答

n, y = gets.chomp.split.map(&:to_i)

not_found = true
# repeated_permutation(3)でも要件は満たすが、組み合わせ爆発でタイムアウトになってしまう
(0..n).to_a.repeated_permutation(2) do |a1, a2|
  a3 = n - a1 - a2
  next if a3 < 0
  next if (a1 + a2 + a3) != n

  sum = a1 * 10_000 + a2 * 5_000 + a3 * 1_000
  if sum == y then
    puts "#{a1} #{a2} #{a3}"
    not_found = false
    break
  end
end

if not_found then
  puts '-1 -1 -1'
end

repeated_permutation は重複順列を出力するメソッドで、レシーバの配列の要素から引数の個数の値を取り出す全てのパターンを出力してくれます。
ブロックを渡せば、順列をブロック引数として受け取って任意の処理を書けるのでそうしています。

コードのコメントにあるように当初はrepeated_permutation(3) でやってみていたのですが、これではパターンが多すぎて、入力値のnが大きい場合はタイムアウトになってしまいました。

(0..2000).to_a.repeated_permutation(3).size
# => 8012006001

nが最大値の2000だった場合、なんと80億件以上です。そりゃ遅いはずです。

しかし、後述の参考サイトを見てrepeated_permutation(2) でもできるとわかったので、それで試してみたらうまくいきました。

(0..2000).to_a.repeated_permutation(2).size
# => 4004001

repeated_permutation(2) にしたら約400万件になりました。多いといえば多いですが、これくらいなら現実的な時間で処理可能なようです。性能が劇的に改善され、nが2000の場合でもタイムアウトせずにクリアできました。

正直、自力で思いつけなかったのは悔しいです。精進します。

参考(というか答え)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0