问题描述:

已知底数a,指数b,取模值p,求 ab % p 的值

 


 

朴素算法

设初始值为1,循环b次,每次乘上a后再取模一下

时间复杂度为O(n),虽然看着不高,但是一旦指数给得过大,肯定会TLE

这里代码就不给出来了,就是一个简单的循环

 


 

快速幂

先不讨论取模,根据幂运算可知

当b为偶数时:ab=a(b/2)*2=(a2)b/2

当b为奇数时:ab=a*ab-1=a*(a2)(b-1)/2

比如:28=44=162=256  直观一点:2*2*2*2*2*2*2*2=4*4*4*4=16*16=256

比如:29=44*2=162*2=256*2=512  直观一点:2*2*2*2*2*2*2*2*2=4*4*4*4*2=16*16*2=256*2=512

也就是每次将指数除以2,底数变为原来的平方,如果指数为奇数,则单独取一个出来另乘

时间复杂度为O(logn)

 1 int pow_mod(int a,int b){
 2     int ans=1,base=a;
 3     while(b){
 4         if(b&1)//等价于判断奇偶
 5             ans*=base;
 6         base*=base;
 7         b>>=1;//将指数除以2
 8     }
 9     return ans;
10 }

 


 

快速幂取模

由于幂的算术递增地非常快,long long也很容易超,这时候就需要取模一下,一般都是模以一个质数

这时候我们需要了解数论中模运算的分配律:

(a*b) % p = ((a % p)*(b % p)) % p

根据上述定理,我们还可以得到:

ab % p = (a % p)b % p

也就是指,在乘法中,模的顺序并不影响最后的结果

然后我们就可以在做快速幂的过程中加上模运算

 1 int pow_mod(int a,int b,int p){
 2     int ans=1,base=a%p;
 3     while(b){
 4         if(b&1)//等价于判断奇偶
 5             ans=(ans*base)%p;
 6         base=(base*base)%p;
 7         b>>=1;//将指数除以2
 8     }
 9     return ans;
10 }