快速幂 (递归/迭代)

本文介绍了快速幂算法的两种实现方式:递归和迭代。递归方法通过将指数n分为偶数和奇数情况来减少运算次数,而迭代方法利用二进制拆分指数,仅对二进制位为1的位置进行乘法操作。两种方法的时间复杂度均为O(log n),但迭代方法具有更低的空间复杂度O(1)。文章通过示例展示了算法的具体过程,并分析了它们的时间和空间复杂度。

快速幂+递归

x64x^{64}x64 : x→x2x^{2}x2x4x^{4}x4x8x^{8}x8x16x^{16}x16x32x^{32}x32x64x^{64}x64 , 只需要把前一个的xkx^kxk自乘一次
x65x^{65}x65: x→x2x^{2}x2x4x^{4}x4x8x^{8}x8x16x^{16}x16x32x^{32}x32x65x^{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也发生变化:tmptmptmptmp2tmp^2tmp2tmp4tmp^4tmp4tmp8tmp^8tmp8 →……
当n的二进制最低位是1的时候,即if(n%2 == 1) 成立时,tmp就可为ans做出贡献。

x11x^{11}x11时,tmp: xxxx2x^2x2x4x^4x4x8x^8x8 , 在这个过程中并不是每一个tmp值都会被乘入ans,我们只需要 xxxx2x^2x2x8x^8x8,即11的二进制为1的位置时的数。

复杂度分析

  • 时间复杂度:O(log nlog\ nlog n), 即为对n进行二进制拆分的时间复杂度
  • 空间复杂度:O(1)

😉

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值