快速幂总结

快速幂问题

即求:\(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个公式:

  1. \(a^b \mod c = [(a \mod c)^b] \mod c\)
  2. \((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\),我们可以得出如下结论:

  1. 当b是偶数,即求\(k^{b/2} \mod c\)
  2. 当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;
}
posted @ 2021-07-01 19:00  C天外天S  阅读(170)  评论(0)    收藏  举报