快速幂、龟速乘总结

快速幂、龟速乘总结

一、快速幂

ab mod p 的结果。

Code

// 快速幂(不加mod)
int qmi(int a, int b) {
    int res = 1;
    while (b) {
        if (b & 1) res = res * a;
        b >>= 1;
        a = a * a;
    }
    return res;
}

// 快速幂
int qmi(int a, int b) {
    int res = 1;
    while (b) {
        if (b & 1) res = (res * a) % MOD;
        b >>= 1;
        a = a * a % MOD;
    }
    return res;
}

解释一下

假如我们需要计算210,正常的办法是

   int s = 1;
   for (int i = 1; i <= 10; i++) s = s * 2;
   cout << s << endl;

毫无疑问,这个算法是正确的。但它执行的次数是10次,有没有什么办法可以优化一下运算次数呢?

优化

10进行二进制分解(10)10=(1010)2
这样处理后,从后向前,借助于我们熟悉的数位分离模板,就是遍历二进制的每一位。

此时,我们发现,最左面的数字1,权值是8,第三位的数字权值是2

同时,2822=210

为什么会有这么神奇的现象呢?其实就是因为幂运算的性质造成:

210=28+2=2822

Q:为啥非得拆成8+2,为啥不拆成7+3呢?
就是因为类似于 倍增 的办法在计算中好处理呗!

a在代码中的使命就是:我不管你用不用的上,反正我每次是翻倍!
而枚举b的每一个数位,就是看看这个位置上的当前a是不是需要乘进来!幂运算的性质成功的把幂与二进制加法结合起来了。

把倍增的思路2,4,8,16,32,...这样长上来的,这是因为
2121=22
2222=24
2424=28
2828=216
216216=232

模板题 : P1226 【模板】快速幂||取余运算

二、龟速乘

ab mod p 的结果,a,b,p 都是 1018 级别。

Code

// 龟速乘,快速加
int qadd(int a, int b) {
    int res = 0;
    while (b) {
        if (b & 1) res = (res + a) % MOD;
        b >>= 1;
        a = (a + a) % MOD;
    }
    return res;
}

这东西怎么理解呢?

举栗子吧

5610=5(110)2

最右侧的0对就的权值是51=5
右侧第二的1对就的权值是52=10
右侧第三的1对就的权值是102=20

对应的位置上有数字1,有效,无效
结果就是10+20=30

posted @   糖豆爸爸  阅读(53)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
历史上的今天:
2013-11-13 广州项目实施步骤III_练习使用Keepalive保证HaProxy的高可用性
2013-11-13 广州项目实施步骤II_练习配置HaProxy的重定向负载均衡
Live2D
点击右上角即可分享
微信分享提示