码迷,mamicode.com
首页 > 其他好文 > 详细

快速幂模板及讲解

时间:2018-06-22 22:46:01      阅读:189      评论:0      收藏:0      [点我收藏+]

标签:time   次方   math   过程   display   pre   优秀   公式   通过   

(这篇其实是我用来练习公式编辑器滴,所以讲的内容略水,大佬们也赏脸看看吧)

定义

快速幂即快速求幂(下文为求a的x次幂模m的结果),但我们一般只在要求对一个数的幂取模时才使用,因为有可能结果很大,有可能long long都存不下,但是因为我们有:
\((ab)\%m=(a\%m)(b\%m)\)
通过转换,可得:
\((a^x)\%m\)
\(= (a\times a\times a\times …\times a(共x个a相乘))\%m\)
\(= (a\%m)\times (a\times a\times a\times …\times a(共x-1个a相乘))\%m\)
\(=((a\%m)\times a\%m)\times (a\times a\times a\times …\times a(共x-2个a相乘))\%m\)
\[……\]
按照这个规律可以一直分解下去,有点类似递归的思想,这样对没一次乘都取模,计算的过程中就不会内存爆炸了

但是只按照上面的方法分解时间复杂度是\(O(x)\),明显不够优秀(摊手手),快速幂一般那个\(x\)都是极其变态滴,比如x都是\(10^8\)级别的,或者有时候还要求很多次的快速幂,这个复杂度明显凉了,但是我们正统的快速幂算法只要\(O(log(x))\)的时间复杂度,这样就算x真的取\(10^8\)也才\(O(27)\)是不是贼快,接下来我就来介绍一下怎么实现

思路

先来说说递归的思路:

int modpow(int a,int x,int mod){……}
表示求a的x次幂,结果对mod取这个算法的核心就是用平方的方法来省事
如果x为偶数,设\(x=2\times k\)
\(a^x=a^{2k}=(a^k)^2\)
然后递归调用modpow(a,x/2,mod)就可以得到\(a^k\)
定义一个新变量(比如tmp)把这个结果存储起来
然后tmp=(tmp\times tmp)%mod;
此时的tmp就是\(a^{2k}\)\(a^x\)
如果x为奇数,设\(x=2\times k+1\)
\(a^x=a^{2k+1}=(a^k)^2\times a\)
\(a^{2k}\)还是要求的,所以上面的步骤还是要做(因为是整除,所以x/2在这里于是等于k)
所以可以在上面的步骤做完后判断一下
if(x%2==1)//即x为奇数
tmp=(tmp*a)%mod;
特别的,如果x为0,立刻返回1(这个肯定没毛病吧)
于是我们的快速幂递归版就闪亮登场了:

int modpow(int a,int x,int mod)//求a的x次幂的递归法,结果对mod取模
{
  if(x==0)
    return 1;
  int tmp=modpow(a,x/2,mod); 
  tmp=(tmp*tmp)%mod;//这里tmp就已经是a的2k次幂
  if(x%2==1)//如果x是奇数
    tmp=(tmp*a)%mod;
  return tmp;
}
然后是非递归思路:

这个方法比较玄学,可以参考一下(我还是比较喜欢递归法)
核心思路是这样的,我们把x转换为二进制,答案初值赋为1,然后如果从右往左数第k位是1,就把答案乘上\(a^{k^2}\),同时在枚举二进制下的x的位数时可以顺便把\(a^{k^2}\)搞了,可以用一个while实现以上步骤,复杂度同样是\(O(log(x))\)(是不是听不懂,没关系看看代码吧):

int poww(int a,int x,int mod){//求a的x次幂的非递归法,结果对mod取模
  int ans=1,base=a;
  while(x>0){
    if(x%2==1)//如果当前这位为1
      ans=(ans*base)%mod;
    base=(base*base)%mod;//这里处理的是a的2k次幂
    x/=2;//这样下一次处理的就是x在二进制下的下一位
  }
  return ans;
}

OK这篇模板讲解就到这咯,一般不会有题目会要求直接求快速幂,可能会换个马甲,也有时候会是一道综合的题目里一个小部分,反正就是不用当心求a的x次方时会超时或超内存,快速幂很优秀

快速幂模板及讲解

标签:time   次方   math   过程   display   pre   优秀   公式   通过   

原文地址:https://www.cnblogs.com/fjyyc/p/9215603.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!