《算法零基础100讲》(第15讲) 二分快速幂[题解]

一.主要知识点

二分快速幂
  二分快速幂的主要思想就是“分而治之”,其通常的表达式为:
在这里插入图片描述
通过这个公式我们很容易想到,需要通过递归的方式实现
代码如下:

int quickMul(int a, int m){
    
    
    if(m == 0){
    
    
        return 1;
    }
    int v = quickMul(a, m / 2);
    return m % 2 == 0 ? v * v : v * v * a;
}

其计算过程的体现方式与二进制转化十进制有些相似。
₃₆₉₄₇₀₅₈
举个例子:
3 ^ 10 = (3 * 3 ^ 5) * (3 ^ 2) * (3 * 3 ^ 1) * (3 ^ 0)
当为奇次幂时要补乘个3
这样,原本通过循环需要计算10次的数据只需计算4次了。

二.课后习题

50. Pow(x, n)


Pow(x, n)的题目链接

在这里插入图片描述

这道题我们只需要区分一下正负即可。
设n大于0,则:
a ^ n = a ^ n
a ^ (-n) = 1 / a ^ n
代码如下:

double quickMul(double a, long long m){
    
    
    if(m == 0){
    
    
        return 1.0;
    }
    double v = quickMul(a, m / 2);
    return m % 2 == 0 ? v * v : v * v * a;
}

double myPow(double x, int n){
    
    
    long long m = n;
    return m >= 0 ? quickMul(x, m) : 1 / quickMul(x, -m);//小于0时取(-m)次方的倒数
}

372. Super Pow


Super Pow的题目链接

在这里插入图片描述

  1. 这道题的主要难点就是数据量过于巨大,最大的数据时计算2000次方,很明显这是不可能实现的,当然题目也要求a ^ b mod1337,但光是计算出结果a ^ b之前(由于我们运用二分快速幂,所以会将a ^ b拆分为多个式子相乘)就已经会出现溢出,所以再计算a ^ b的过程中我们也要进行mod,但随便取模是会导致结果发生变化的,这是我们便要运用到公式:
(a * b) % k = (a % k) * (b % k) % k
  1. 现在我们解决了求幂的问题,由于我们所得到的幂数据是由数组d组成的,所以我们还要考虑如何进行转化。
    举个例子:
    在这里插入图片描述
    我们不难发现这个问题我们也能用递归的方式解决,从尾部开始计算。
    代码如下:
#define mod 1337
int mypow(int a,int b){
    
    
    if(b == 0)return 1;
    a %= mod;
    if(b % 2 == 1){
    
    
        return a * mypow(a, b - 1);
    }
    else{
    
    
        int sum = mypow(a, b / 2);
        return (sum % mod) * (sum % mod) % mod;
    }
}

int superPow(int a, int* b, int bSize){
    
    
    if(!bSize)return 1;
    int ans;
    ans = mypow(a, b[bSize - 1]) * mypow(superPow(a, b, bSize - 1), 10);
    return ans % mod;
}

Guess you like

Origin blog.csdn.net/qq_53060585/article/details/121146181