快速幂+递归
求x64x^{64}x64 : x→x2x^{2}x2→ x4x^{4}x4→ x8x^{8}x8→ x16x^{16}x16→ x32x^{32}x32→ x64x^{64}x64 , 只需要把前一个的xkx^kxk自乘一次
求x65x^{65}x65: x→x2x^{2}x2→ x4x^{4}x4→ x8x^{8}x8→ x16x^{16}x16→ x32x^{32}x32→ x65x^{65}x65 , 在x32x^{32}x32自乘一次后还要再乘一个x
求xnx^{n}xn: ①若n为偶数, xnx^{n}xn = xn/2x^{n/2}xn/2 * xn/2x^{n/2}xn/2 = x(n/2)∗2x^{(n/2)*2}x(n/2)∗2 ; ②若n为奇数, xnx^{n}xn = xn/2x^{n/2}xn/2 * xn/2x^{n/2}xn/2 * x,(其中xn/2x^{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(log nlog\ nlog n), 即为递归的层数
- 空间复杂度:O(log nlog\ nlog n), 即为递归的层数。这是因为递归的函数调用会使用栈空间
快速幂+迭代
求x11x^{11}x11 : 11的二进制:1011,于是x11x^{11}x11 = x(20+21+23)x^{(2^0 + 2^1 + 2^3)}x(20+21+23) = x(20)x^{(2^0)}x(20) * x(21)x^{(2^1)}x(21) *x(23)x^{(2^3)}x(23) = x * x2x^{2}x2 * x8x^{8}x8, 只要分别求xix^ixi再相乘,不用将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也发生变化:tmptmptmp → tmp2tmp^2tmp2 → tmp4tmp^4tmp4 →tmp8tmp^8tmp8 →……
当n的二进制最低位是1的时候,即if(n%2 == 1) 成立时,tmp就可为ans做出贡献。
求x11x^{11}x11时,tmp: xxx → x2x^2x2 → x4x^4x4 →x8x^8x8 , 在这个过程中并不是每一个tmp值都会被乘入ans,我们只需要 xxx ,x2x^2x2 和x8x^8x8,即11的二进制为1的位置时的数。
复杂度分析
- 时间复杂度:O(log nlog\ nlog n), 即为对n进行二进制拆分的时间复杂度
- 空间复杂度:O(1)
😉
本文介绍了快速幂算法的两种实现方式:递归和迭代。递归方法通过将指数n分为偶数和奇数情况来减少运算次数,而迭代方法利用二进制拆分指数,仅对二进制位为1的位置进行乘法操作。两种方法的时间复杂度均为O(log n),但迭代方法具有更低的空间复杂度O(1)。文章通过示例展示了算法的具体过程,并分析了它们的时间和空间复杂度。
564

被折叠的 条评论
为什么被折叠?



