快速幂基本性质和一些优化写法

前言,高次幂的一般计算:

求 a^b % m的值,时间复杂度O(b)

利用for来写,每一次循环都 mod m (利用模运算—>可在网站首页搜索"模运算"了解同模运算加减乘除定理)

结果:b接近于10亿时,计算机运算时间接近于18秒

快速幂的简单介绍:

快速幂的递归写法

前言:

我们知道,3^4= 3^2 * 3^2 = 3^1 * 3^1 * 3^1 * 3^1 ;

那么我们如果先将32的值计算出来,储存在临时变量p中,那么此时,34中需要计算的量就为:

3^4= 3^2 * 3^2 = 3^1 * 3^1 * 3^1 * 3^1 ;–>只计算了两次

此时a^b运算的时间复杂度 从O (b) 变为了 O (logb)

实现方式,递归思想;
注意点:当出现3^5这种指数为奇数的情况时,我们可以写成 3^1 * 3^4 的形式,即当ab,b为奇数时,我们将其写成a(b-1) * a 的形式

递归代码:

typedef long long ll;
int ans;
int quick_pow(int base,int power,int mod)//base为底数,power为指数
{
    ll p;
    if(power==0)
    return 1;
    if(power%2)
    return base%mod*quick_pow(base,power-1,mod)%mod;
    else
    {
        p=quick_pow(base,power/2,mod)%mod;
        return p*p%mod;
    }
}
如何将递归形式简化写成while()形式:

我们知道 例如3^8= 3^4 * 3^4 其实可以写成 38=(34)2=(32)4,即当ab,b为偶数时,我们可以写成(a2)(b/2),将上述的quick_pow(base,power/2,mod) * quick_pow(base,power/2,mod),简化为,a=a * a后,令b/=2;

且当b为奇数时,a^b=a * a^(b-1)—>这个a并不是初始的底数而是当前的a,将此时的a用ans=ans * a将其“收集”起来,而最终,b为1时,也会有ans=ans * a,所以最终ans为答案

举例:a^7=a * a^6=a * (a2)3 =a * a^2 * (a2)2=… 其中 其一步 ans将 a 收集起来 第二步 将 a^2 收集起来…

while()形式代码:

int quick_pow(ll base,ll power,int mod)
{
    ll ans=1;
    while(power!=0)
    {
        if(power&1)
        ans=ans*base%mod,power--;
        else
        base=base*base%mod,power/=2;
    }
    return ans;
}

注意这里利用了位运算&,在这里的作用为判读奇偶。

为什么使用位运算:位运算消耗的时间更短。

位运算的其他用法请参考:

https://blog.csdn.net/weixin_42216574/article/details/82885102

快速幂的迭代形式:

例:a ^13 = a^1 * a^4 * a^8,是因为13的二进制 1101。

所以我们可以将a^b 表示成 ∏a(2符合条件的i) (∏为连乘)。若b二进制中i+1位为1则符合条件。

且由于每进一位,a->a2->(a2)^2->。。。

所以我们可以先定义一个ans,从b的二进制第一位(最右边)开始,若a&b为1,则说明,这一位为1,那么ans * =a,否则,不乘,进入下一位,实行操作a=a * a b>>=1; 直到b取尽。

代码

int quick_pow(ll base,ll power,int mod)
{
    ll ans=1;
    while(power>0)
    {
        if(power&1)//判断二进制下第一位是否为1
        ans=ans*base%mod;
        base=base*base%mod,power>>=1;
    }
    return ans;
}

如此一来,进一步降低了复杂度,使得快速幂更加高效。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wizardAEI

喜欢就投喂一下吧O(∩_∩)O

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值