快速幂
初次见面,想和大家先谈一谈快速幂,这是一个比较简单易懂的算法,我们先来康康最死板也是最容易想到的方法就是可以模仿math.h这个头文件里的pow函数来求a的b次幂。
如下
int pow(int a,int b)
{
int i,ans=1;
for(i=0;i<b;i++)
ans*=a;
}
可以看到,算法的时间复杂度是O(n)。为了降低时间复杂度,我们可以使用快速幂算法,将时间复杂度降低到O(logn),n是幂。
快速幂的原理:
还是原来的,我们会发现,其实指数b是可以拆成二进制的。通过式子,我们可以发现,一旦指数b拆成二进制,那么也可以进行相应的拆分。那么,我们完全可以想到如果要计算a的n次方,我们可以先把a的二次方给求出来,那么a的四次方即是a的二次方的平方,a的八次方即是a的四次方的平方,以此类推,我们就可以以O(logn)的时间复杂度把a的n次方给求出来,当然,这还是在n是2的整数倍数的情况下,而对于形如2的六次方怎么计算,我们可以反过来想,先把2的三次方给求出来,而怎么求2的三次方这种奇数次幂呢,我们只需要增加一个判断条件即可
如果幂为奇数,我们就让其分割,看成是a的偶数次幂再乘以a
代码是:
ans*=a;
好啦,说了这么多,我们来聊点实际的,来康康完整代码如何实现
#include<stdio.h>
int main(void)
{
int a,b,i,j,ans;
scanf("%d%d",&a,&b);
while(b>0)
{
if(b%2==1)
ans*=a;
a*=a;
b/=2;
}
printf("%d\n",ans);
}
是不是康起来很简单呀,我相信你们会理解的,好啦,当我们知道了代码的原理之后我们还要学会运用啊,现在在很多市面上的编程题都需要用到快速幂求模运算,先在就由小初再给大家啰嗦两句咯。
快速幂求模
让我们先来康康必须要记住的数学公式
当麻烦的数学公式记住了以后,我相信聪明小伙伴们都马上有了自己的想法,但是阔以先参考参考才疏学浅的小初同学的想法呀
假设是求a^b%c
我们最容易想到的,就是先把最后的答案给%c,这没有问题,如果一开始a的值就很大,那么我们就阔以根据枯燥的公式呀,先把一开始的a给进行求模,当然,有个时候c的值也很大,那么这个语句的作用就显得微乎其微了,几乎不能缩短运算的难度,我们先康康代码
#include<stdio.h>
int main(void)
{
int a,b,c,i,j,ans;
scanf("%d%d%d",&a,&b,&c);
a=a%c;//加上这一句
while(b>0)
{
if(b%2==1)
ans*=a;
a*=a;
b/=2;
}
ans=ans%c;//再加上这一句
printf("%d\n",ans);
}
这个代码是不是康起来几乎没有改变,大家别急,小初想循序渐进,为了真正改进算法,我们还需要依赖一个数学公式
而根据这个数学公式我们又阔以写出新的代码,这次将直接在循环里面改变呢!
#include<stdio.h>
int main(void)
{
int a,b,i,j,ans,c;
scanf("%d%d%d",&a,&b,&c);
a=a%c;
while(b>0)
{
if(b%2==1)
ans=(ans*a)%c;
a=(a*a)%c;
b/=2;
}
ans=ans%c;
printf("%d\n",ans);
}
好啦,小初的想法和代码已经写好啦,那么小初也就到此为止了,可能讲的得也有点迷迷糊糊的,还请大家见谅,那么更好的算法就小初就等着你们来发掘了。最后,再一次感谢大家的浏览(如果阔以双击或一键三连的话,小初就阔以在拼多多上帮你砍一刀)