快速幂定义

1.参考

参考:数据结构与算法 - 矩阵快速幂

2.思路

如果直接求取 M^n,时间复杂度是 O(n),可以用快速幂算法来加速这里 M^n的求取, 简化时间复杂度为 O(logn)
主体思路就是不求 M^n 而是求 M^(n/2), 然后先不求M^(n/2), 先求M^(n/4)

代码

1.递归实现快速幂

最直接的写法是使用递归:(求x^n)
这里if (n & 1) 是判断奇偶性的, 决定是 midmidx 还是 mid*mid, 结束条件 x^0 = 1;

double _myPow(double x, long long n)
{
    if (n == 0)
        return 1;
    if (n < 0)
        return 1 / _myPow(x, -n);
    double mid = _myPow(x, n / 2);
    if (n & 1)
        return mid * mid * x;
    return mid * mid;
}

2.二进制分解

此外还有另外一个代码实现技巧:二进制分解,n -> 1, 2, 4, 8, 16, 32。n 可以分解为 2 的幂次的和 。
例如 13 = 8 + 4 + 1, 求 a^13 需要求 a^8, a^4, a^1, 可以用变量存 a^1, a^2, ..., a^(n-1)
如果当前幂次是 n 需要的,则加到结果中。如何判断当前幂次是否需要,可以用位掩码来决定,即下面代码中的 n&1。

在代码中,通过循环进行迭代,每次迭代都将指数 N 右移一位(相当于除以 2),同时将底数 M 平方。
这样就相当于把指数 N 不断地除以 2,并且将底数 M 不断地平方,直到指数 N 变为 0。
在每一次迭代中,如果当前位为 1(即 n & 1 的结果为非零),就将结果乘以当前的底数 M。

主要思路就是标志+还原(标志:这里通过二进制位是否为1判断是否相乘; 还原: 配合a *= a; 底数a平方次增长, 还原对应的二进制位数使用 n >>= 1即可解决)
比如像13 = 1101
我们这里的 a^1 对应的第0位开始判断, 如果为1, 说明需要乘上;
然后

int quickpower(int a, int n)
{
    // a==0 && n==0 特判
    int ans = 1; // n = 0 时候不进循环
    while(n)
    {
        if(n & 1) ans *= a;
        a *= a;
        n >>= 1;
    }
    return ans;
}

3.例子

可看 50.Pow(x,n) _

posted @ 2024-04-26 23:33  DawnTraveler  阅读(3)  评论(0编辑  收藏  举报