LoginSignup
3
1

More than 5 years have passed since last update.

~ これだけ解けば十分闘える!過去問精選 10 問 ~ の8問目 Otoshidama をPHPで

Last updated at Posted at 2018-03-31

すでにPHPの記事があった orz

Qiitaで珍しくAtCoderの記事が話題になっていました。

AtCoder に登録したら次にやること ~ これだけ解けば十分闘える!過去問精選 10 問 ~

これのPHPで解いてみた版を書こうと思ったら、もうありました orz

ただ、特に解説とかなかったので、書いてみても良いかなぁ、と。

過去問と言っても、だいたい解いちゃってるかなぁ、なんて思っていたんですが、8問目以降の300点問題は全部やってませんでした。

そんな訳で、今回は8問目を。

お年玉の合計金額とお札の合計枚数が与えられるので、
1万円札と5000円札と1000円札それぞれの枚数を1例出力せよ。

実現不可能な場合は「-1 -1 -1」を出力せよ。

という問題です。

1万円札と5000円札の枚数を仮に決めれば、1000円札の枚数は必然的に求まりますので、 O(n^2) で計算可能です。

もちろん、その場合には、時間制限に引っかかります。

<?php
fscanf(STDIN, "%d %d", $N, $Y);

for ($k10 = 0; $k10 * 10000 <= $Y; $k10++) {
    for ($k5 = 0; $k10 * 10000 + $k5 * 5000 <= $Y; $k5++) {
        $k1 = ($Y - $k10 * 10000 - $k5 * 5000) / 1000;
        // printf("k10:%d k5:%d k1:%d\n", $k10, $k5, $k1);
        if ($k10 + $k5 + $k1 == $N) {
            echo "{$k10} {$k5} {$k1}" . PHP_EOL;
            exit;
        }
    }
}
echo "-1 -1 -1" . PHP_EOL;

image.png

引っかかりませんでした ((((;゚Д゚))))ガクガクブルブル

とは言え、実行時間が442ms(0.442秒)かかっています。
もうちょっと工夫してみましょう。

もうちょっと工夫して高速化

まず、1万円札の枚数だけ、仮に決めます。
残りを一旦、1000円札だけにします。
その後に、1000円札を5000円札に交換する儀式をすることにします。
変動するのは1万円札の枚数だけなので、計算量は O(n) です。

1000円札を5000円札に交換する儀式をすると、1000円札 5 枚が5000円札 1 枚になるので、 1回儀式を行うたびに、お札の合計が 4 枚減ります。
つまり、1万円札と1000円札の時点で、Nより 4の倍数枚 多い場合は、儀式によってピッタリの枚数にすることができます。
(※計算上、お札が0枚未満になる場合は除外します)

最初のプログラムでは、5000円札もループしていましたが、今回は5000円札の枚数を1回の計算で求めているので、高速になるはずです。

コードで書くと、こんな感じです。

<?php
fscanf(STDIN, "%d %d", $N, $Y);

$answer = "-1 -1 -1";

$k10max = floor($Y / 10000);
for ($k10 = 0; $k10 <= $k10max; $k10++) {
    $k1 = ($Y - $k10 * 10000) / 1000;
    if ((($k10 + $k1) - $N) % 4 == 0) {
        $k5 = (($k10 + $k1) - $N) / 4;
        $k1 -= $k5 * 5;
        if ($k5 < 0 || $k1 < 0) continue;

        $answer = "{$k10} {$k5} {$k1}";
        break;
    }
}

echo $answer . PHP_EOL;

image.png

実行時間が9ms(0.009秒)になりました。
ざっくり計算すると50倍くらいの速さで計算が終了したことになります。

……では!

3
1
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
3
1