首先了解了

取模的运算的性质

 

                    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;
}