快速幂(Binary Exponentiation)
它可以以 Θ ( l o g n ) \Theta (logn) Θ(logn) 的时间复杂度计算乘方。
法一:递归
原理:
若
n
n
n 为偶数:
a
n
=
a
n
/
2
∗
a
n
/
2
=
a
n
/
4
∗
a
n
/
4
∗
a
n
/
4
∗
a
n
/
4
\begin{equation*} \begin{aligned} a^n &= a^{n/2} * a^{n/2} \\ &= a^{n/4} *a^{n/4}*a^{n/4}*a^{n/4} \\ \end{aligned} \end{equation*}
an=an/2∗an/2=an/4∗an/4∗an/4∗an/4
运用了二分的思想,使求幂的过程尽可能少。
递归边界为: a 0 = 1 a^0=1 a0=1
long long binaryPow(long long a, long long b)
{
if(b == 0) return 1;
else if(b%2==1) return a*binaryPow(a,b-1);
else
{
long long num = binaryPow(a, b/2);
return num * num;
}
// 不写成return binaryPow(a, b/2) * binaryPow(a, b/2)
}
long long binaryPow(long long a, long long b)
{
if (b == 0) return 1;
long long res = binaryPow(a, b / 2);
if (b % 2)
return res * res * a;
else
return res * res;
}
法二:
我们把幂数 b b b写成二进制 b = ( b n b n − 1 . . . b 2 b 1 ) 2 b=(b_nb_{n-1}...b_2b_1)_2 b=(bnbn−1...b2b1)2。
有: b = ( b n ∗ 2 n + b n − 1 ∗ 2 n − 1 + . . . + b 2 ∗ 2 + b 1 ∗ 1 ) b=(b_n*2^n+b_{n-1}*2^{n-1}+...+b_2*2+b_1*1) b=(bn∗2n+bn−1∗2n−1+...+b2∗2+b1∗1)。其中,$b_i = 0,1 $。
所以, a b = a ( b n b n − 1 . . . b 2 b 1 ) 2 a^b=a^{(b_nb_{n-1}...b_2b_1)_2} ab=a(bnbn−1...b2b1)2
而 n n n 有 ⌊ l o g 2 n ⌋ + 1 \lfloor log_2n \rfloor +1 ⌊log2n⌋+1 个二进制位,由此,幂运算得到优化:
long long binaryPow(long long a, long long b)
{
long long res = 1;
while (b > 0)
{
if (b & 1) res = res * a;//如果b的二进制末位为1。
a = a * a;//对应的二进制位倍数。
b >>= 1;//b右移1位。
}
return res;
}