简介:快速幂算法可以将a^k%p以O(log k)的时间复杂度算出来。其中a和p在1e9左右的范围内都可以。
原理:我们先求出来a^(2^0)、a^(2^1)、a^(2^2)、a^(2^3)。。。a^(2^log k),然后将a^k用前面那些式子的乘积的形式表示出来,至于模p,在那些式子后面分别模p就行了。
快速幂的原理用的是平方法。观察a^(2^0)、a^(2^1)、a^(2^2)、a^(2^3)。。。a^(2^log k)这些式子,其实后一个数都是前一个数的平方。
怎样将a^k用^(2^0)、a^(2^1)、a^(2^2)、a^(2^3)。。。a^(2^log k)的乘积表示出来呢?很简单。假设a^k=a^(2^x1) * a^(2^x2) * ...*a^(2^xt),那么a^k就等于a^(2^x1+2^x2+...2^xt),也就是我们要让k等于2^x1+2^x2+...2^xt,怎样让它们俩相等呢?很简单。这其实就是求一下k的二进制编码而已。比如k的二进制表示为10011,那么k就等于1*2^0+1*2^1+0*2^2+0*2^3+0*2^4+1*2^5.
ok,那么快速幂的原理就是先将k用二进制表示,然后通过二进制将k用a^(2^0)、a^(2^1)、a^(2^2)、a^(2^3)。。。a^(2^log k)的乘积表示,中间注意取模就行了。
时间复杂度:快速幂程序中的循环其实是k的二进制位数,即log k(以2为底),因此你写一个快速幂的函数,时间复杂度为O(log k)。
//快速幂,求a^k%p
ll qsm(ll a,ll k,ll p)
{
ll res=1;//先把res处理为1,便于以后相乘
while(k)
{
if(k&1) res=res*a%p;//如果k的最后一位为1,那么结果累乘a
k>>=1;//k右移一位,为了遍历k的每一位
a=a*a%p;//a是累乘的,从a^1累乘到a^(log k)
}
return res;
}
随便写出来划划水。。。