快速幂(数学应用)

当要求a ^ b % p时,若a、b、p的数据不算很大时直接调用pow()函数最为方便,但考虑a、b、p的数量级均达到千万甚至上亿时想用pow()在短时间内得到结果几乎是不可能的想法甚至计算机还可能出现爆long的情况,这时候快速幂相当排得上用场。

 


我们都知道取模运算中 (A*B) %P = (A%P*B%P)%P

幂运算a ^ b本质也是一种乘法运算即b 个 a 相乘,所以由上式可得在每次“×”的时候先取一次模在相乘,循环下去最终可以得到结果,快速幂借用这种思想一次一次地把幂降下来,当幂为1时,底数即为结果,降幂均为折半(若为奇数则减一折半)。

为了保持结果不变,幂的折半同时对应底数的翻倍,并且取一次模运算,对比传统求幂的做法要循环n次(n为幂),而快速幂只需循环不超过logn次运算即可得到最终结果,这也正是其优化后时间效率较高的地方。


朴素做法:

long long quick_pow(long long base, long long power, long long p){
    long long res = 1;        //迭代的结果
    while(power > 0){
        if(power % 2 == 0){
            power /= 2;
            base = base * base % p;
        }
        else{
            power -= 1;
            res = res * base % p;    /*幂为奇数减一位后,底要多乘一次,而这次记录到res上代替base ^ power的结果*/
            power /= 2;
            base = base * base % p;
        }
    }
    return res % p;
}

再快一点:

上面的做法已经实现了快速幂算法,而还可以对其再进行优化一下使代码更简洁,我们都知道机器处理位运算时非常快,所以考虑将判断奇偶运算用"&"来代替,即power & 1 == 0表示为偶数;同时还能将折半运算用">>"来代替,即power >>= 1,右移一位。而奇偶情况下都有power /= 2;        base = base * base % p;操作,不妨将其拿出判断语句,只是在power为奇时把要乘的一次base记录到res上。所以最终就可以简化为如下形式:

long long quick_pow(long long base, long long power, long long p){
    long long res = 1;        //迭代的结果
    while(power){
        if(power & 1 == 1){
            res = res * base % p;
        }
        power >>= 1;
        base = base * base % p;
    }
    return res % p;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值