倍增与快速幂,快速乘

倍增与快速幂,快速乘

一.快速幂

  • 快速幂分为递归快速幂迭代快速幂
  • 目的是求:a^n,常与大素数的取模运算结合
  • 时间复杂度:O(log n)

递归快速幂:

迭代方程:

[公式]

//递归快速幂
int qpow(int a, int n)
{
    if (n == 0)
        return 1;
    else if (n % 2 == 1)
        return qpow(a, n - 1) * a;
    else
    {
        int temp = qpow(a, n / 2);
        return temp * temp;
    }
}

加上取模运算:

//递归快速幂(对大素数取模)
#define MOD 1000000007
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 % MOD;
    else
    {
        ll temp = qpow(a, n / 2) % MOD;
        return temp * temp % MOD;
    }
}

注意:temp相当重要,无temp时间复杂度会变成o(n)

迭代快速幂:

想明白原理的话,这里强烈推荐观看结尾第一个链接的博客,十分清晰。

//非递归快速幂
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;
}

泛型推广:

//泛型的非递归快速幂
template <typename T>
T qpow(T a, ll n)
{
    T ans = 1; // 赋值为乘法单位元,可能要根据构造函数修改
    while (n)
    {
        if (n & 1)
            ans = ans * a; // 这里就最好别用自乘了,不然重载完*还要重载*=,有点麻烦。
        n >>= 1;
        a = a * a;
    }
    return ans;
}

建议记忆此模板算法!

快速乘仅需将上述乘法修改为加法即可。

参考博客:

https://zhuanlan.zhihu.com/p/95902286

https://www.cnblogs.com/RioTian/p/14542241.html

posted @ 2021-10-12 17:33  秋月桐  阅读(120)  评论(0编辑  收藏  举报