1.引入
我们首先来思考一个问题,求一个数a的b次方。这个问题看起来是不是很简单,下面的代码就可以轻松解决。
#include <bits/stdc++.h>
using namespace std;
int a,b;
int main(){
cin>>a>>b;
cout<<pow(a,b)<<endl;
return 0;
}
这个代码的时间复杂度是O(N)这样写的话,等于小的数据还可以做,但是数据如果很大的话,就算开unsigned long long也不行,所以我们需要一种更快,并且能算的数更大的算法,而这就是快速幂算法。
2.快速幂的介绍
快速幂,顾名思义,就是快速算底数的n次幂。其时间复杂度为 O(log₂N), 与朴素的O(N)相比效率有了极大的提高。而怎么达到O(log₂N)的呢,那就是用二进制的思想。
我们可以举一个例子:
3^10=3 * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3
= (3 * 3) * (3 * 3) * (3 * 3) * (3 * 3) * (3 * 3)
=(3 * 3) ^ 5
=9 ^ 5
=(9 ^ 4) * (9 ^ 1)
=(6561 ^ 1) * (9 ^ 1)
那对于a的b次方,,我们也可以转换成二进制的方式。
我们可以将b转换成二进制数,例如b=11,那么b就等于2 ^ 0 + 2 ^ 1 + 2 ^ 3,那么ab =a^(2 ^ 0 + 2 ^ 1 + 2 ^ 3),那么就可以变成a ^ (2 ^ 0)*a ^ (2 ^ 1)*a ^ (2 ^ 3)。
3.代码实现
既然我们知道了是用二进制来实现,那就可以将这个数不断拆分,不断的算底数的平方就可以了。
long long qkpow(long long a,long long b){
long long sum=1;
while(b){
if(b&1) sum*=a;
a*=a;
b>>=1;
}
return sum;
}
4.总结
快速幂一般是用于在边幂运算边取模的,例如在写欧拉定理时就要用到快速幂,快速幂在一般情况下是完全够用的,但也无法避免还要大的数,所以快速幂也还可以再优化,想了解的可以自行查阅资料。