快速幂

快速幂

幂还有快速?

我们首先来思考一个问题,对于 $7^6$ 如何求。

作为一个人类,你的求法一定是先算出 $7\times7=49$,然后接着算出 $49\times7=343$,…… ,$16807\times7=117649$。因为人类并不适合算两位数以上的乘法(一位数还勉强可以瞪眼),所以有些时候我们的思维便会限制在这个里面。

但是,我们了解,对于计算机CPU来说 $7\times7$ 和 $1561564\times1561564$ 几乎没啥差别(毕竟慢的是存储),因此我们可以加快幂运算。

又是二进制

没错,你没看错,又是二进制!

我们早就知道了,对于任意一个二进制数,我们可以拆分成多个 $2^n$ 相加的形式。如:$6_{10}=(110)_2=(100)_2+(10)_2=2^2+2^1$。

相应的,任意一个数 $x$ 的 $k$ 次方 $x^k$ 都可以拆分成多个 $x^{2^n}$ 相乘的形式。这时候,我们发现,原本的 $O(k)$ 次操作被优化到了 $O(\log{k})$。而我们只需要将 $x^{2^n}$ 不断的自己乘自己,就可以得到所有我们需要的数。

例子:计算 $7^{14}=7^2\times7^4\times7^8$

代码

[P1226 【模板】快速幂&取余运算][https://www.luogu.com.cn/problem/P1226]

//只需要注意mi函数即可
#include <cstdio>
int a, b, p;
inline int mi(int n, int m, int mod, long long sum = 1, long long ans = 1)
//n表示底数,m表示指数,mod为模数,sum为累加器,ans为结果
{
    sum = n;  //初始化累加器至n^1
    while (m) //保证指数不为0
    {
        if (m & 1) //如果最后一位是1,则应该乘上
        {
            ans *= sum;
            ans %= mod;
        }
        sum *= sum; //累加器自乘
        sum %= mod;
        m >>= 1; //这一位已经处理完毕,开始处理下一位
    }
    return ans % mod;
}
int main()
{
    scanf("%d%d%d", &a, &b, &p);
    printf("%d^%d mod %d=%d\n", a, b, p, mi(a, b, p)); //奇奇怪怪的输出方式
}

链接

其他更快的方法,参见[]、[]。

曦曦呵呵
曦曦呵呵
一名卑微的OIer。

开开心心,蹦蹦跳跳~

上一页