Official

B - Hydrate Editorial by penguinman


実は、高橋くんの目標が達成可能な場合必要な操作回数の最小値は \(A\) 以下になります。その理由を説明します。

まずはじめに、問題文中の操作や高橋くんの目標を数式で表してみましょう。高橋くんが \(x\) 回目の操作を行ったあと、箱の中のボールの個数はそれぞれ以下の通りになっています。

  • 水色のボールの個数 \(\cdots\) \(A+Bx\)
  • 赤色のボールの個数 \(\cdots\) \(Cx\)

また、高橋くんの目標が達成されるためには、以下が成り立っている必要があります。

  • (水色のボールの個数) \(\leq D \times\)(赤色のボールの個数)

よってこの問題は以下のように表すことができます。

  • \(A+Bx \leq D \times Cx\) を満たすような非負整数 \(x\) は存在するか。存在するなら、そのような \(x\) の最小値を求めよ。

\(A+Bx \leq D \times Cx\) を式変形してみましょう。

\[ A+Bx \leq D \times Cx \\ \Leftrightarrow A \leq (CDx-Bx) \\ \Leftrightarrow A \leq (CD-B)x \]

明らかに、\(CD-B\) が非正であるなら高橋くんの目標は達成されません。そうでない場合、\(x\)\(\frac{A}{CD-B}\) の切り上げとなります。\(CD-B\) は正整数ですから、\(x\) の値は \(A\) 以下となります。

故に必要な操作回数の最小値が \(A\) 以下になることが示されました。このように、答えの上限を見積もることは非常に重要です。

実装の際は以下のように \(Θ(A)\) 回のループを回して判定すればよいです。オーバーフローには注意しましょう。

実装例 (C++)

#include<bits/stdc++.h>
using namespace std;

int main(){
    long long A,B,C,D; cin >> A >> B >> C >> D;
    long long blue = A, red = 0;
    for(int i = 1; i <= A; i++){
        blue += B;
        red += C;
        if(blue <= D*red){
            cout << i << endl;
            return 0;
        }
    }
    cout << -1 << endl;
}

なお、次のように \(O(1)\) 回の計算で答えを求めることも可能です。

実装例 (Python)

A,B,C,D = map(int,input().split())
ans = -1
diff = C*D-B
if 0 < diff:
    ans = (A+diff-1)//diff
print(ans)

posted:
last update: