はまやんはまやんはまやん

hamayanhamayan's blog

オーバーフローファンタジー [yukicoder No.598]

https://yukicoder.me/problems/no/598

解法

https://yukicoder.me/submissions/218480

最小回数で倒すには攻撃し続けるか回復し続けるかしかない。
攻撃し続けて倒す場合はceil(X / A)回やればいい。
(ceil関数は小数点切り上げ)
回復し続けて倒す場合には、Nビット目が最初に1になるまで足していけばいい。
オーバーフローすることを無視して考えると、Nビット目が1になっている数は(1<<(N-1))以上の数である。
上限を超えれば倒せるので、回復して足す必要がある差分xは(1<<(N-1))-X分である。
よって、回復し続けて倒す場合にはceil(x / B)回やればいい。
あとは、回数が小さい方を答える。

typedef long long ll;
int N; ll X, A, B;
//---------------------------------------------------------------------------------------------------
void _main() {
    cin >> N >> X >> A >> B;

    // 攻撃で倒す
    ll attack = X / A;
    if (X % A != 0) attack++;

    // 回復で倒す
    ll x = (1LL << (N - 1)) - X;
    ll cure = x / B;
    if (x % B != 0) cure++;

    ll ans = min(attack, cure);
    cout << ans << endl;
}