快速幂算法+取模

快速幂

用途: 顾名思义,快速幂就是很快速的幂运算,
复杂度: O(logn)
实现原理:
image
规律:

  • 如果指数是偶数,直接将底数平方,指数处以2;
  • 如果指数是奇数,将底数平方,指数除以2,再乘上底数。

模板代码:

ll qpow(ll a,ll b) //a是底数,b是指数
{
    ll ans=1;//ans是结果的系数
    while(b)
    {
        if(b%2==1)
        {
            ans=ans*a;
        }
        b/=2;
        a=a*a;
    }
    return ans;
}

位运算优化代码:


ll qpow(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1)
      {
       ans=ans*a;
      }
        a=a*a;
        b>>=1;
    }
    return ans;
}

快速幂取模公式:
(a×b)%m = ((a%m)×(b%m))%m;
推广:
  (a × a × a...)%c
 = ( (a%c)×(a%c)×(a%c)×... )%c
 = (a%c)b %c;

取模模板代码:

ll qpow(ll a,ll b)
{
    ll ans=1;
    a%=mod;
    while(b)
    {
        if(b%2==1)
        {
            ans=(ans*a)%mod;
        }
        b/=2;
        a=(a*a) %mod;
    }
    return ans;
}

位运算优化代码:

ll qpow(ll a,ll b)
{
    ll ans=1;
    a%=mod;
    while(b)
    {
        if(b&1)
            ans=ans*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return ans;
}

龟速乘

因为本来两个数相乘的时间复杂度是O(1),而用了这种方法后时间复杂度变为了O(logN),故称龟速乘。

作用: 用于两个大数相乘还要求取模的情况。

实现方式:
将其中一个乘数分解成2的幂次相加,

比如数字5的二进制表示为101,我们把它看成是\(2^2 + 2^0\),则5 * a可以看成\(2^2 * a + 2^0 * a\),这就是龟速乘。

代码

#include <iostream>
using namespace std;
typedef long long LL;
LL qadd(LL a, LL b, LL p)
{
    LL res = 0;
    while (b)
    {
        //将变量b看成是二进制形式,若当前位为1,则更新取模的结果
        if (b & 1) res = (res + a) % p;
        b >>= 1;
        a = (a + a) % p;
    }
    return res;
}

int main()
{
    LL a, b, p;
    cin >> a >> b >> p;
    cout << qadd(a, b, p) << endl;
    return 0;
}
posted @ 2021-09-12 11:11  kingwzun  阅读(735)  评论(0编辑  收藏  举报