首先了解了
取模的运算的性质
a%b=r;
a=kb+r;
则可知当a对r取模时实际上kb%b=0
所以对于幂的模运算
a^n为(kb+r)^ 分成多个kb+r的乘积
乘法模运算看这里————————((kb+r1)(kb+r2) )==(kb^2 + kb* (r1+r2) + r1*r2 )%b;
有kb的又被消掉啦~~最后剩下(r1*r2)%b;
运用二项式定理我们只取没有Kb的部分所以我们可以得到
a^n % b =( (r)^n % b )%b;
所以!!
a^b%c
对于b我们可以拆成二进制的形式
b=b0+b1*2+b2*2^2+...+bn*2^n
这里我们的b0对应的是b二进制的第一位
那么我们的a^b运算就可以拆解成
a^b0*a^b1*2*1...*a^(bn*2^n)
对于b来说,二进制位不是0就是1,那么对于bx为0的项我们的计算结果是1就不用考虑了,我们真正想要的其实是b的非0二进制位
那么假设除去了b的0的二进制位之后我们得到的式子是
a^(bx*2^x)*...*a(bn*2^n)
这里我们再应用我们一开始提到的公式,那么我们的a^b%c运算就可以转化为
(a^(bx*2^x)%c)*...*(a^(bn*2^n)%c)
这样的话,我们就很接近快速幂的本质了
(a^(bx*2^x)%c)*...*(a^(bn*2^n)%c)
我们会发现令
A1=(a^(bx*2^x)%c)
An=(a^(bn*2^n)%c)
这样的话,An始终是A(n-1)的平方倍(当然加进去了取模匀速那),依次递推
1.如果b是偶数,我们可以记
k = a2 mod c,那么求 (k)b/2 mod c就可以了。
2.如果b是奇数,我们也可以记 ((k)b/2 mod c × a ) mod c 就可以了。
现在我们来考虑实现它:
--------这段为引用
int fast_pow(int a,int b,int c)
{
int ans=1; ///记录结果
a=a%c; ///预处理,使得a处于c的数据范围之下
while(b!=0)
{
if(b&1)///奇数
{
ans=(ans*a)%c;///消除指数为奇数的影响
}
b>>=1; ///二进制的移位操作,不断的遍历b的二进制位
a=(a*a)%c; ///不断的加倍
}
return ans;
}