快速幂+递归
求
x
64
x^{64}
x64 : x→
x
2
x^{2}
x2→
x
4
x^{4}
x4→
x
8
x^{8}
x8→
x
16
x^{16}
x16→
x
32
x^{32}
x32→
x
64
x^{64}
x64 , 只需要把前一个的
x
k
x^k
xk自乘一次
求
x
65
x^{65}
x65: x→
x
2
x^{2}
x2→
x
4
x^{4}
x4→
x
8
x^{8}
x8→
x
16
x^{16}
x16→
x
32
x^{32}
x32→
x
65
x^{65}
x65 , 在
x
32
x^{32}
x32自乘一次后还要再乘一个x
求
x
n
x^{n}
xn: ①若n为偶数,
x
n
x^{n}
xn =
x
n
/
2
x^{n/2}
xn/2 *
x
n
/
2
x^{n/2}
xn/2 =
x
(
n
/
2
)
∗
2
x^{(n/2)*2}
x(n/2)∗2 ; ②若n为奇数,
x
n
x^{n}
xn =
x
n
/
2
x^{n/2}
xn/2 *
x
n
/
2
x^{n/2}
xn/2 * x,(其中
x
n
/
2
x^{n/2}
xn/2中n/2 为n/2向下取整后的数,如65/2=32.5,向下取整为32)
double myPow(double x, long long int n)
{
if(n == 0) return 1.0;
double y = myPow(x, n/2);
return n%2==1 ? y*y*x : y*y;
}
int main()
{
double x; int n;
cin >> x >> n;
long long int N = n;
double ans = N >= 0 ? myPow(x, N) : 1.0/myPow(x, -N);
cout << ans << endl;
return 0;
}
输入:2.00000 10
输出:1024.00000
输入:2.10000 3
输出:9.26100
输入:2.00000 -2
输出:0.25000
复杂度分析
- 时间复杂度:O( l o g n log\ n log n), 即为递归的层数
- 空间复杂度:O( l o g n log\ n log n), 即为递归的层数。这是因为递归的函数调用会使用栈空间
快速幂+迭代
求 x 11 x^{11} x11 : 11的二进制:1011,于是 x 11 x^{11} x11 = x ( 2 0 + 2 1 + 2 3 ) x^{(2^0 + 2^1 + 2^3)} x(20+21+23) = x ( 2 0 ) x^{(2^0)} x(20) * x ( 2 1 ) x^{(2^1)} x(21) * x ( 2 3 ) x^{(2^3)} x(23) = x * x 2 x^{2} x2 * x 8 x^{8} x8, 只要分别求 x i x^i xi再相乘,不用将x连乘11次
double myPow(double x, long long int n)
{
double ans = 1.0, tmp = x;
while(n)
{
if(n%2 == 1) // 指数二进制末尾为1
ans *= tmp;
tmp *= tmp;
n/=2; // 舍去二进制最低位
}
return ans;
}
int main()
{
double x; int n;
cin >> x >> n;
long long int N = n;
double ans = N >= 0 ? myPow(x, N) : 1.0/myPow(x, -N);
printf("%.5f\n", ans);
return 0;
}
关于tmp*=tmp
tmp最初等于x,
随着n右移舍去最低位,tmp也发生变化:
t
m
p
tmp
tmp →
t
m
p
2
tmp^2
tmp2 →
t
m
p
4
tmp^4
tmp4 →
t
m
p
8
tmp^8
tmp8 →……
当n的二进制最低位是1的时候,即if(n%2 == 1) 成立时,tmp就可为ans做出贡献。
求
x
11
x^{11}
x11时,tmp:
x
x
x →
x
2
x^2
x2 →
x
4
x^4
x4 →
x
8
x^8
x8 , 在这个过程中并不是每一个tmp值都会被乘入ans,我们只需要
x
x
x ,
x
2
x^2
x2 和
x
8
x^8
x8,即11的二进制为1的位置时的数。
复杂度分析
- 时间复杂度:O( l o g n log\ n log n), 即为对n进行二进制拆分的时间复杂度
- 空间复杂度:O(1)
😉