AtCoder Beginners Selectionから,ABC085C - Otoshidamaを解きました.
問題はこちら.
解法
Pythonで書いてます.
n, y = list(map(int, input().split()))
a = b = c = 0
yen_a = 10000
yen_b = 5000
yen_c = 1000
target = y - yen_c * n
coef_a = yen_a - yen_c
coef_b = yen_b - yen_c
a = int(target / coef_a)
if a > n or target < 0:
a = b = c = -1
else:
while a >= 0:
if coef_a * a + coef_b * b == target and n-a-b >= 0:
c = n - a - b
break
elif coef_a * a + coef_b * b > target:
a -= 1
else:
b += 1
if a == -1:
b = c = -1
print(a, b, c)
我ながらあまり美しくないコードだなと思いますが,残念ながら自力で解くとこんなものですね.
追記:
@c-yan さんにprint()
の小技を教えていただいたので,print()
部分を変更しました.@c-yan さんありがとうございます!
@DaikiSuyama さんにコメントいただいた部分を修正しました.@DaikiSuyama さんありがとうございます!
解説
上の方では標準入力を受け取ったり,変数を初期化したりしています.
if文の前のブロックでは,2つの3元一次方程式から,2元一次方程式を導き出しています.以下の数式の中からc
を消去するような処理です.
\left\{
\begin{array}{l}
a + b + c &=& n \\
10000a + 5000b + 1000c &=& y
\end{array}
\right.
結果こんな式になります.
9000a + 4000b = y - 1000n
後はこれを満たす(a, b)
の組み合わせを探します.
a = int(target / coef_a)
で上の数式を満たす最大のa
を導き出しています.a > n
の場合,つまりお札の枚数が少なくて,目標の金額に届かない場合とtarget < 0
の場合,これはお札の枚数が多すぎて表現できる最小金額を目標金額が下回る場合のことですが,この2通りの場合に指定されたお札の枚数で目標金額を表現することはできないということで,a = b = c = -1
にしています.
その後は,上記以外の場合で,a
,b
の値を上下させて上式を満たす組み合わせがないかを探しています.
あとがき
反省点としては,最初からa + b + c = n
の範囲で全件調べればよかったなと思いました.
私の方法は全然いい方法ではないので,こちらの解法を参照してください.
問題を解くのに加えて,プログラムの内容を言葉で説明するのは頭の体操になっていいなぁと思いました.