算法 - 快速乘/幂算法

快速乘/幂算法

算法思想

在对两个数进行乘法运算的时候,我们一般是直接使用库函数或者是用运算符号“”直接进行计算。但是乘法在计算机中处理的时间并不是这么快的,也要拆分为加法来做的。所以快速乘法会更快地计算ab的结果,如果数字过大就可能会出现溢出的问题,但快速乘法却不会。快速幂也是同样的道理。

例如:5 * 53 = 5 * 110101(二进制表示53)
= 5 * (100000 * 1 + 10000 * 1 + 1000 * 0 + 100 * 1 + 10 * 0 + 1 * 1)
= 5 * (2^5 * 1 + 2^4 * 1 + 2^3 * 0 + 2^2 * 1 + 2^1 * 0 + 2^0 * 1)
= 5 * 2^5 * 1 + 5 * 2^4 * 1 + 5 * 2^3 * 0 + 5 * 2^2 * 1 + 5 * 2^1 * 0 + 5 * 2^0 * 1
从结果可以看出,当a0 = 5的时候,a1 = 5 * 2 * (1或者0,这个取决于第二个因数中的二进制位取1还是0)
在这里插入图片描述
其实对于快速幂其实是一样的道理,只不过每一位a更新的时候不是2,而是a=aa。
例如3^5的流程:
3^5
= 3^(1001) (二进制)
= 3^(10001+1000+100+11)
在这里插入图片描述

Java代码实现

    public long q_mul(long a,long b) {
          long result = 0;
          while (b != 0) {
             if ((b & 1) != 0) {
                 result = result + b % 2 * a; // b%2获取到第二个因数二进制位数的最后一位
             }
             a = a * 2; // 后一个计算结果是前一个的2倍,例如:a0 * 2 = a1
             b = b / 2; // 第二个因数向右移动一位
         }
       return result;
    }
     public long q_pow(long a,long b) {
          long result = 0;
          while (b != 0) {
             if ((b & 1) != 0) {
                result = (result + a) % mod;
            }
             a = a * a; 
             b = b / 2; 
         }
       return result;
    }

适用范围

快速计算a*b % mod的结果(主要目的是换乘法为加法,防止爆数据),或者快速计算a^b % mod 的结果,时间复杂度大大降低。

 public long q_mul(long a,long b) {
       long result = 0;
       while (b != 0) {
         if ((b & 1) != 0) {
           result = result + b % 2 * a;
         }
         a = a * 2;
         b = b / 2;
       }
       return result;
    }

    public long q_mul_mod(long a,long b,long mod) {
        long result = 0;

        while (b != 0) {
            if ((b & 1) != 0) {
                result = (result + (b % 2 * a) % mod) % mod;
            }
            a = (a * 2) % mod;
            b = b / 2;
        }

        return result;

    }

    public long q_pow_mul_mod(long a,long b,long mod) {
        long result = 0;

        while (b != 0) {

            if ((b & 1) != 0) {
                result = (result + a) % mod;
            }

            a = (a + a) % mod;
            b = b / 2;
        }

        return result;

    }

    public long q_pow_mod(long a,long b,long mod) {
        long result = 1;

        while (b != 0) {

            if ((b & 1) != 0) {
                result = q_pow_mul_mod(result,a,mod);
            }

            a = q_pow_mul_mod(a,a,mod);
            b = b / 2;
        }

        return result;

    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值