SRM664 Div1 Easy BearPlays
問題
自然数の組 $(X,Y)$ が与えられる.$X\leq Y$ なら $(2X,Y-X)$ に,そうでなければ $(X-Y,2Y)$ に置き換えるという操作を $K$ 回繰り返す.その後の $X,Y$ のうち小さい方を求めよ.
方針
$S=X+Y$ として $\mathrm{mod}\ S$ で考える.
- $X \leq Y$ のとき $X \to 2X$
- $X>Y$ のとき $X \to X-Y = X-(S-X) = 2X-S = 2X$
になるので,いずれにせよ $\mathrm{mod}\ S$ で $2$ 倍にしてるだけ. $K$ 回繰り返せば $2^K$ 倍になるので,結局 $X2^K$ が最終的な $X$ の値になる. そのときの $Y$ は $S-X$ となるので, $\min(X,S-X)$ を返す. $K$ 乗の部分は繰り返し二乗法で高速に求める.
実装
class BearPlays {
public:
ll A,B,K;
int pileSize( int A_, int B_, int K_ ) {
A = A_;
B = B_;
K = K_;
ll S = A+B;
ll res1 = A*modpow(2,K,S)%S;
ll res2 = S-res1;
return min(res1,res2);
}
ll modpow(ll a, ll b, ll m){
if(b==0) return 1;
ll x = modpow(a,b/2,m);
ll res = x*x%m;
return (b&1)==1 ? res*a%m : res;
}
};