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; }