快速幂总结
快速幂问题
即求:\(a^b \mod c\)
暴力
直接暴力
时间复杂度:\(O(b)\)
int ans = 1,i;
for(i=0;i<b;i++)
ans *= a;
ans %= c;
问题在于当a,b过大时,容易溢出。
优化溢出
时间复杂度:\(O(b)\)
首先明确2个公式:
- \(a^b \mod c = [(a \mod c)^b] \mod c\)
- \((a*b) \mod c = [(a \mod c)*(b \mod c)] \mod c\)
即:积的取余等于取余的积的取余!
证明:
设:\(d = a \mod c, e = b \mod c\)
则:\(a = t*c+d, b = k*c+e\)
可以推出:
\[a*b \equiv x*c+d*e \equiv d*e \pmod c
\]
公式1可由公式2推得。
int ans = 1,i;
a %= c;
for(i=0;i<b;i++)
ans *= a;
ans %= c;
这个改进不大,只是减小了数据溢出的可能。
快速幂
时间复杂度:\(O(\log_2{b})\)
公式:
\[a^b \mod c = (a^2)^ \left( b/2 \right) \mod c, 当b为偶
\]
\[a^b \mod c = ((a^2)^ \left( b/2 \right) * a) \mod c, 当b为奇
\]
依据上述两个公式,令\(k = a^2 \mod c\),我们可以得出如下结论:
- 当b是偶数,即求\(k^{b/2} \mod c\)
- 当b是奇数,即求\(((k^{b/2} \mod c) * a) \mod c\)
每次用此公式迭代即为快速幂取余算法!
int ans = 1;
a %= c;
while(b>0)
{
if(b%2==1) ans = (ans *a)%c;
b /= 2;
a = (a*a)%c;
}
看了算法竞赛(刘汝佳)之后发现还有一种写法,思想相同,用递归实现,代码:
int pow_mod(int a,int b,int c)
{
if(b==0) return 1;
int x = pow_mod(a,b/2,c);
long long ans = (long long)x * x % c;
if(b%2==1) ans = ans * a % c;
return (int)ans;
}

浙公网安备 33010602011771号