什么是快速幂
顾名思义,快速幂就是快速算底数的 n n n 次幂。其时间复杂度为 O ( l o g 2 N ) O(log₂N) O(log2N), 与朴素的 O ( N ) O(N) O(N) 相比效率有了极大的提高。
原理分析
快速幂算法的核心思想就是每一步都把指数分成两半,而相应的底数做平方运算。这样不仅能把非常大的指数给不断变小,所需要执行的循环次数也变小,而最后表示的结果却一直不会变。
例如:
3
10
=
3
∗
3
∗
3
∗
3
∗
3
∗
3
∗
3
∗
3
∗
3
∗
3
3^{10}=3*3*3*3*3*3*3*3*3*3
310=3∗3∗3∗3∗3∗3∗3∗3∗3∗3
3
10
=
(
3
∗
3
)
∗
(
3
∗
3
)
∗
(
3
∗
3
)
∗
(
3
∗
3
)
∗
(
3
∗
3
)
3^{10}=(3*3)*(3*3)*(3*3)*(3*3)*(3*3)
310=(3∗3)∗(3∗3)∗(3∗3)∗(3∗3)∗(3∗3)
3
10
=
(
3
∗
3
)
5
3^{10}=(3*3)^5
310=(3∗3)5
3
10
=
9
5
3^{10}=9^5
310=95
9
5
=
9
4
∗
9
1
9^5=9^4*9^1
95=94∗91
9
5
=
656
1
1
∗
9
1
9^5=6561^1*9^1
95=65611∗91
因为是求
a
b
a^b
ab ,所以可以把b转换成二进制数。则这个二进制数第
i
i
i 位的权为
a
i
−
1
a_{i-1}
ai−1,例如:
当
b
=
11
当 b=11
当b=11
a
11
=
a
2
0
+
a
2
1
+
a
2
3
a^{11}=a^{2^0}+a^{2^1}+a^{2^3}
a11=a20+a21+a23
11
的二进制为
1011
11 的二进制为 1011
11的二进制为1011
11
=
2
3
×
1
+
2
2
×
0
+
2
1
×
1
+
2
0
×
1
{11}={2^3}×1+{2^2}×0+{2^1}×1+{2^0}×1
11=23×1+22×0+21×1+20×1
所以,
a
11
a^{11}
a11 转换为:
a
2
0
+
a
2
1
+
a
2
3
a^{2^0}+a^{2^1}+a^{2^3}
a20+a21+a23
代码实现
我们可以直接用位运算来实现。
STEP1
既然是位运算,那么就需要将 b b b 转换为二进制。则:
int qmi(int a,int b)//求a的b次方
{
//STEP1
int res=1;//用来记录最后的值
while(b)
{
b>>=1;
}
return res;
}
STEP2
根据上文分析,我们得知:每次的 b b b 均需 &1,判断其这一位是否为1,。若是1,则 r e s = r e s × a res=res×a res=res×a。否则不运算(即乘0)。记得,每次判断后 a a a 均要将指数加 1 1 1。代码如下:
int qmi(int a,int b)//求a的b次方
{
//STEP1
int res=1;//用来记录最后的值
while(b)
{
//STEP2
if(b&1)
{
res=res*a;
}
a=a*a;
b>>=1;
}
return res;
}
总结
快速幂也没什么难点,就算不理解,也能将其背下来。也许,硬背和理解的唯一不同就是你根本不知道这个函数为什么要位运算。