快速幂板子
一、递归实现
原理:
a
n
=
{
a
n
−
1
a
当
n
为
奇
数
a
n
/
2
a
n
/
2
当
n
为
偶
数
且
不
为
0
1
当
n
为
0
a^{n}=\begin{cases}a^{n-1}a \quad\ \ \ \ 当n为奇数\\ a^{n/2}a^{n/2}\quad 当n为偶数且不为0 \\1 \quad \quad \quad \quad当n为0 \end{cases}
an=⎩⎪⎨⎪⎧an−1a 当n为奇数an/2an/2当n为偶数且不为01当n为0
代码实现
//递归快速幂
typedef long long ll;
ll qpow(ll a, ll n)
{
if (n == 0)
return 1;
else if (n % 2 == 1)
return qpow(a, n - 1) * a;
else
{
ll temp = qpow(a, n / 2);
return temp * temp;
}
}
取模再自己加
递归算法虽然简洁, 但是会产生额外的栈空间开销. 我们试图将递归算法转为非递归算法.
二、非递归实现
原理:
我们这回用二进制的思路来考虑求幂的问题
例如 , 计算 7 10 7^{10} 710
7
10
=
7
101
0
(
2
)
7^{10}=7^{1010_{(2)}}
710=71010(2), 我们将其拆成
7
100
0
(
2
)
×
7
001
0
(
2
)
7^{1000_{(2)}}\times 7^{0010_{(2)}}
71000(2)×70010(2),也就是指数化为二进制中该位为1的数,即在二进制意义下, 指数是可以通过位运算来拆分的(其实就是一个10进制数的指数可以化为二进制数,化为几个
2
n
2^n
2n相加)
代码实现
//非递归快速幂
int qpow(int a, int n){
int ans = 1;
while(n){
if(n&1) //如果n的当前末位为1
ans *= a; //ans乘上当前的a
a *= a; //a自乘
n >>= 1; //n往右移一位
}
return ans;
}
其实相当于
int qpow(int a, int n){
int ans = 1;
while(n){
if(n % 2) //奇数情况
ans *= a; //ans乘上当前的a
a *= a; //a自乘(底数平方)
n /= 2; //指数减半
}
return ans;
}