Topcoder SRM 664 DIV 1
BearPlays 快速幂
题意:
给你两个数A,B,有种操作是将大的数减去小的数,并将小的数乘以2。反复k次,问你最后的小的数回是多少。
题解:
由于整个过程$A+B$的值是不会改变的。现在令$S=A+B$,那么这两种操作可以看作如下两种形式:
若$A$是较小的那个数,那么$A=A*2$
若$A$是较大的那个数,那么$A=A-B=A-(S-A)=A*2-S$,由于$S*2>=A*2$,则$A=A*2 mod S$
所以我们发现实际上就是计算$A*2^k mod S$,这里用快速幂即可。算法复杂度是$O(logk)$
代码:
LL PowerMod(LL a, LL b, LL c) { LL ans = 1; a = a % c; while(b>0) { if(b % 2 == 1) ans = (ans * a) % c; b = b/2; a = (a * a) % c; } return ans; } class BearPlays { public: int pileSize(int A, int B, int K) { LL s=A+B; LL t=PowerMod(2,K,s); return min(A*t%s,B*t%s); } };