快速幂算法

快 速 幂 算 法

这次在参加网络算法比赛中遇到需要算多次幂的问题,即求出4i从n到m的累加和,虽然n和m之间的间隔不超过105,但是本身n和m的范围是从1到1019,这意味着如果我每个都从头开始算它的4次幂,算法复杂度要O(n2),即便我从1次幂开始算一直到算到m次幂,复杂度降到O(n),可是这个n的范围是从1到1019,也远远达不到题目要求的时间限制。

所以这里需要用到快速幂算法,每算出一个指定幂的时间复杂度为log2(n)。

快速幂思想

我们知道如果让一个数本身乘以本身,不断重复下去,你会发现什么规律?

举例5这个数,伪代码,第一次5*5=25,第二次25*25=625,第三次625*625……化成指数形式就是51*51=52,52*52=54,54*54=58……

我们可以发现上面等号左边的数指数以2n-1的规律往下走,等号右边的数的规律则是2n

如果我想要算出5的13次幂这个数,13这个数用2次幂来表示怎么表示?熟悉二进制的人都知道应该是1101=8+4+1=13,即23+22+20

聪明的人可能已经发现这两者之间的规律了——用二进制表示的数来表示之前幂次,当当前幂次是目标幂次的和的部分时,则取当前幂次;否则不取。

至于如何判断当前幂次是否是目标幂次的和的部分,前面其实已经说了,1310=11012,每个为1的部分都是你的目标幂次所需要的部分,每次循环的时候让当前幂次数和1相与&,如果为1说明当前幂次数是你所需要的。

C++代码如下:

 1 long long fastpower(long long base,long long e)
 2 {
 3     long long sum=1;
    //base为底数,e为指定幂次数,sum是求出指定幂次数的结果
4 while(e) 5 { 6 if(e&1) 7 sum=sum*base; 8 e=e>>1; 9 base=base*base; 10 } 11 return sum; 12 }

 -------------------------------------------------------------------------2021.3.1日(●'◡'●)分割线---------------------------------------------------------------------------------------------

这次2021牛客寒假算法训练营练习中碰到了快速幂求逆元的问题,这里简单阐述一下问题来源:

在正常的算法比赛中,经常会遇到需要对结果进行取模的题目,而一般取模的题目是并不是只是对结果取模即可,而是要对整个过程中迭代的数据进行取模,而取模后的数如果要进行除法该怎么办?

我们正常对取模后的数进行恢复都是需要商的,即商*模数+取模后的数=原来的数(可能大佬们有别的办法吧呜呜。我正常都是这样算的),但我们不可能对这些所有迭代过程中的商都进行记录,因为真的毫无意义而且浪费空间。。。

因此这里需要用到快速幂算法求乘法逆元。参考https://blog.csdn.net/Kerryliuyue/article/details/107849522

根据这个大佬的解释可以得出一个结论:a/b=a*bm-2。b与m必须互质且为整数,当模数m为质数时,bm-2即为b的乘法逆元。

再根据上文的快速幂算法模板,就可以算出这个乘法逆元了。

posted @ 2021-01-02 15:53  miyui  阅读(324)  评论(0)    收藏  举报