乘法快速幂相关总结

发布于 2024-05-15 08:37:59 字数 4843 浏览 14 评论 0

递归计算 (a <sup>n</sup>) % mod

递归计算其实是更容易理解的:

  • 为了求 an,我们先递归去求出 an/2,得到结果记录为 halfRes
  • 然后如果 n 为偶数,很好办,再乘以一个 halfRes 就可以了(再取模一下),也就是可以返回 halfRes*halfRes
  • 但是如果 n 为奇数的话,就需要再乘以一个 a ,然后再返回;

幂分解

代码:

    static long pow_mod(long a, long n, long mod) {
        if (n == 0)      // a^0 = 1
            return 1;
        // 先求一半的 --> 你先给我求出 a ^ (n/2) 的结果给我
        long halfRes = pow_mod(a, n >> 1, mod); // n >> 1 --> n/2

        long res = halfRes * halfRes % mod;

        if ((n & 1) != 0)       // odd num
            res = res * a % mod;
        return res;
    }

非递归计算 (a <sup>n</sup>) % mod

假设一个整数是 10 ,如何最快的求解 1075 次方。

  • 75 的二进制形式为 1001011
  • 1075 次方 = 1064 × 108 × 102 × 101
  • 在这个过程中,我们先求出101,然后根据101求出102,再根据102求出104。。。。,最后根据1032求出106475 的二进制数形式总共有多少位,我们就使用了多少次乘法;
  • ③ 在步骤②进行的过程中,把应该累乘的值相乘即可,比如1064108102101应该累乘,因为 64、8、2、1 对应到 75 的二进制数中,相应位上是 1 ;而10321016、104不应该累乘,因为 32、16、 4 对应到 75 的二进制数中,相应位是 0
    static long pow_mod2(long a, long n, long mod) {
        long res = 1;
        while (n > 0) {
            if ((n & 1) != 0) // 二进制最低位 是 1 --> (n&1) != 0  -->  乘上 x ^ (2^i)   (i 从 0 开始)
                res = res * a % mod;
            a = a * a % mod;  // a = a^2
            n >>= 1;          // n -> n/2      往右边移一位
        }
        return res;
    }

使用 a ^ 11 来模拟一下计算过程:

计算 ( a * b ) % mod

	// 计算 (a * b) % mod
    static long mul_mod(long a, long b, long mod){
        long res = 0;

        while(b > 0){
            if( (b&1) != 0)  // 二进制最低位是 1 --> 加上 a 的 2^i 倍, 快速幂是乘上 a 的 2^i )
                res  = ( res + a) % mod;
            a = (a << 1) % mod;    // a = a * 2    a 随着 b 中二进制位数而扩大 每次 扩大两倍。
            b >>= 1;               // b -> b/2     右移  去掉最后一位 因为当前最后一位我们用完了,
        }

        return res;
    }

配合 ( a * b ) % mod 和乘法快速幂

可以使用非递归的乘法快速幂和上面的 (a*b) % mod 来计算快速幂,差别不大:

    // 计算 (a * b) % mod
    static long mul_mod(long a,long b,long mod){
        long res = 0;
        while(b > 0){
            if( (b&1) != 0)  // 二进制最低位是 1 --> 加上 a 的 2^i 倍, 快速幂是乘上 a 的 2^i )
                res  = ( res + a) % mod;
            a = (a << 1) % mod;    // a = a * 2    a 随着 b 中二进制位数而扩大 每次 扩大两倍。
            b >>= 1;               // b -> b/2     右移  去掉最后一位 因为当前最后一位我们用完了,
        }
        return res;
    }

    //非递归 计算 (a^n) % mod   配合 mul
    static long pow_mod3(long a,long n,long mod){
        long res = 1;
        while(n > 0) {
            if( (n&1) != 0 ) // 二进制最低位 是 1 --> (n&1) != 0  -->  乘上 x ^ (2^i)   (i 从 0 开始)
                res = mul_mod(res,a,mod) % mod;
            a = mul_mod(a,a,mod) % mod;  // a = a^2
            n >>= 1;          // n -> n/2      往右边移一位
        }
        return res;
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

八巷

暂无简介

0 文章
0 评论
21 人气
更多

推荐作者

qq_E2Iff7

文章 0 评论 0

Archangel

文章 0 评论 0

freedog

文章 0 评论 0

Hunk

文章 0 评论 0

18819270189

文章 0 评论 0

wenkai

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文