快速幂(从最容易想到的思路一直到最终算法形成)
快速幂顾名思义是快速求出底数的n次幂的算法
初步了解
例题:人见人爱A^B
这个题目看起来很简单,但是考虑到了数据范围之后可能就会卡住
首先我们根据开始的想法写一下
int main()
{
while(1)
{
scanf("%d%d",&a,&b);
if(a == 0 && b == 0)
return 0;
ans = 1;
for(int i = 1;i <= b;i++)
ans *= a;
ans %= 1000;
printf("%d\n",ans);
}
return 0;
}
然而结果可不会如你所愿,int型不可能承受的了,即使换上long long也毫无意义。
根据模运算进行改进
那么接下来根据模运算的特性对代码再进行调整
(a * b) % mod == (a % mod) * (b % mod) % mod
int main()
{
while(1)
{
scanf("%d%d",&a,&b);
if(a == 0 && b == 0)
return 0;
ans = 1;
for(int i = 1;i <= b;i++)
ans = (ans % 1000) * (a % 1000) % 1000;
printf("%d\n",ans);
}
return 0;
}
现在再看一下运行结果:
根据代码我们清楚的知道时间复杂度是O(n),对于一般的算法来说这已经算是比较优化的算法了,然而,现在让你计算2^10000000000的运行结果,那么当你运行的时候就只能慢慢等了,一般来说1s大概跑10的7次方,而这里是10次方,等待时间……
本次算法主题
现在就解决时间复杂度的问题。我们可以这么考虑2^10000000000
可以写成4^5000000000……一直优化下去那么又将时间复杂度从O(n)降到了O(logn)
具体如何解决就直接可以看代码
int main()
{
while(1)
{
scanf("%d%d",&a,&b);
if(a == 0 && b == 0)
return 0;
ans = 1;
while(b > 0)
{
if(b % 2)
ans = ans * a % 1000;
a = a * a % 1000;
b /= 2;
}
printf("%d\n",ans);
}
return 0;
}
如果还要进一步优化的话,将模运算换成位运算
if(b % 2) -->if(b & 1)
具体见 位运算