快速幂

为降低原来O(b)的时间复杂度,求解a^b%m,现在利用二分的思想,进行求解。
a^b=a *a^(b-1) b为奇数
ab=a(b/2)*a^(b/2) b为偶数
在经过O(ln(b))级别的转换后,就可以将b变成0;

还要必须知道的是 a b…n%m=(a%m)(b%m)…(n%m)%m.
另外%,/ ,*的优先级一样。

#include<cstdio>
typedef long long LL;
LL binaryPow(LL a,LL b,LL m) {
    if (b == 0) return 1;
    if (b & 1)  return a * binaryPow(a, b - 1, m) % m;
    else {
        LL mul = binaryPow(a, b / 2, m);
        return mul * mul%m;//此处不要返回binaryPow(a, b / 2, m)*binaryPow(a, b / 2, m);因为这样每次都会调用两个binaryPow(a, b / 2, m),导致复杂度变为O(b).
    }
}

添加两个细节:
如果初始的时候a有可能大于等于m;那么需要在进入函数之前就让a对m取模。ab…n%m=(a%m)(b%m)…(n%m)%m.
如果m=1,可以直接在函数外面判断特例为0;
下面是快速幂的迭代的写法。
对于a^b,可以把b写成二进制,那么b就可以写成若干二次幂之和。
例如:
13==》1101;三号位,二号位,零号位都为1,则 13=2^3 +2^2 +2^0=8+4+1;
a^13=a^8*a^4*a^1;

typedef long long LL;
LL binaryPow(LL a,LL b,LL m) {
    LL ans = 1;
    while (b > 0) {
        if (b & 1) {
            ans = ans * a %m;
        }
        a = a * a % m;
        b >>= 1;
    }
    return ans;
}

当b=13时可有以下过程

 

posted @ 2021-04-17 18:26  银发制御  阅读(46)  评论(0)    收藏  举报