原理
快速幂是对以下形式的式子进行计算
A n A^n An
其中,A可以是整数、浮点数、矩阵等。n只能是整数,因为这是能够让这个计算变快的原因。
传统的幂次计算需要进行n-1次乘法,时间复杂度为O(n), 如下
A
n
=
A
×
A
×
.
.
×
A
⏟
n
个
\begin{matrix} A^n = \\ \ \end{matrix} \ \begin{matrix} \underbrace{ A\times A \times ..\times A } \\ n 个 \end{matrix}
An=
A×A×..×An个
但是快速幂算法,把计算过程拆分成如下形式。假设n是一个32位整数无符号数,
n
i
∈
{
0
,
1
}
n_i\in \{0, 1\}
ni∈{0,1}表示n的二进制表示中从右往左数第i位。i从0开始。
n
=
n
0
2
0
+
n
1
2
1
+
.
.
.
+
n
31
2
31
n=n_02^0+n_12^1 + ... + n_{31}2^{31}
n=n020+n121+...+n31231
A
n
=
A
n
0
2
0
+
n
1
2
1
+
.
.
.
+
n
31
2
31
=
A
n
0
2
0
×
A
n
1
2
1
×
.
.
×
A
n
31
2
31
\begin{split} A^n &= A^{n_02^0+n_12^1 + ... + n_{31}2^{31}} \\ &= A^{n_02^0} \times A^{n_12^1} \times ..\times A^{n_{31}2^{31}} \end{split}
An=An020+n121+...+n31231=An020×An121×..×An31231
由此可见,分解后一共有32项相乘。如果每一项都能在O(1)时间内解决,则总的乘法计算次数不会超过31次。实际的次数会小于31,取决于n中比特1的个数,因为如果
n
i
=
0
n_i = 0
ni=0, 那么该项不需要被乘,直接跳过这一项的计算。
对于
n
n
n来说,比特1
的个数不会超过
l
o
g
2
n
log_2n
log2n。因此总的时间复杂度为
O
(
l
o
g
2
n
)
O(log_2n)
O(log2n)。
知道了计算量是如何减小的,现在关键是怎么在O(1)的时间内计算其中每一项。可以利用递推的思想。如下:
A
2
0
=
A
1
=
A
A
2
1
=
A
2
=
A
1
×
A
1
A
2
1
=
A
4
=
A
2
×
A
2
A
2
3
=
A
8
=
A
4
×
A
4
.
.
.
A
2
31
=
A
2147483648
=
A
2
30
×
A
2
30
\begin{split} A^{2^0} &= A^1 = A \\ A^{2^1} &= A^2 = A^1\times A^1 \\ A^{2^1} &= A^4 = A^2\times A^2 \\ A^{2^3} &= A^8 = A^4\times A^4 \\ ...& \\ A^{2^{31}} &= A^{2147483648} = A^{2^{30}}\times A^{2^{30}} \\ \end{split}
A20A21A21A23...A231=A1=A=A2=A1×A1=A4=A2×A2=A8=A4×A4=A2147483648=A230×A230
代码
代码如下:
int pow(int a,int n){
int ans = 1;
while(n > 0){
if((n & 1) == 1){
ans *= a;
}
a *= a;
n >>= 1;
}
return ans;
}