mayoko’s diary

プロコンとかいろいろ。

SRM 664 div1 easy:BearPlays

SRM 664に参加しました。easyを通してレート上昇です。うれしいけどmed解きたい…

解法

結論から言うと
tmp = min(A, B) * 2^K mod (A+B)
として,min(tmp, A+B-tmp)が答えです。(2^K mod (A+B))はO(log K)で高速に計算ができるのでこれで時間内に答えを得られます。

理由を考えてみます(N=A+Bとする)。

(A, B)の大小関係関係なくAを2倍することを考えます。

AがB以下の場合は当然この操作は正しいです。
一方AがBより大きい場合は,問題文中の操作ではBを2倍することになるので,この操作を素直にやると,A = N-2*Bとなります。

一方で,Aを2倍してmod Nをとる操作は,2*A-N = 2*(N-B)-N = N-2*Bとなり,上記の操作と一致します。

よって,この「2倍してmod Nをとる」という操作をK回やることは問題文中の操作をやることと一致します。ゆえに,上に書いた解法は正しいです。

ll pow_mod(ll x, ll p, ll mod) {
    if (x == 0) return 0;
    if (p == 0) return 1;
    if (p == 1) return x;
    if (p%2) return (pow_mod(x, p-1, mod) * x) % mod;
    ll tmp = pow_mod(x, p/2, mod);
    return (tmp*tmp)%mod;
}

class BearPlays {
public:
    int pileSize(int A, int B, int K) {
        ll N = A+B;
        ll mi = min(A, B);
        ll ans = pow_mod(2, K, N);
        (ans *= mi) %= N;
        return min(ans, N-ans);
    }
};