问题描述:
已知底数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 }