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);
        }
};
View Code

 

posted @ 2015-09-02 19:27  好地方bug  阅读(308)  评论(0编辑  收藏  举报