算法竞赛模板 快速乘与快速幂

取英文首字母来命名函数名称:

(1) multiply乘;(2) power-幂;(3) quick-快速;(4) mod-取模

①快速乘

由于计算机底层设计的原因,做加法往往比乘法快的多,因此将乘法转换为加法计算将会大大提高乘法运算的速度,除此之外,当我们计算 a*b%mod 的时候,往往较大的数计算 a*b 会超出long long int的范围,这个时候使用快速乘法方法也能解决上述问题。
快速乘法的原理就是利用乘法分配率来将a*b转化为多个式子相加的形式求解(注意这时使用乘法分配率的时候后面的一个乘数转化为二进制的形式计算)
eg:20*14 = 20*(1110)= 20*(2^3)*1 + 20*(2^2)*1+20*(2^1)*+20*(2^0)*0 = 160+80+40 = 280

typedef long long ll;
ll qm(ll a,ll b)
{
    ll ans=0;
    while(b)
    {
        if(b&1)
            ans+=a;
        b>>=1;
        a<<=1;
    }
    return ans;
}

 

②快速乘取模

typedef long long ll;
ll qmm(ll a,ll b,ll mod)
{
    ll ans=0;
    while(b)
    {
        if(b&1)
            ans=(ans+a)%mod;
        a<<=1;
        b>>=1;
    }
    return ans;
}

 

③快速幂

typedef long long ll;
ll qp(ll x,ll p)
{
    ll ans=1;
    while(p)
    {
        if(p&1)
            ans*=x;
        p>>=1;
        x*=x;
    }
    return ans;
}

 

④快速幂取模(二阶),即求(x^p)%mod

typedef long long ll;
ll qpm(ll x,ll p,ll mod)
{
    ll ans=1;
    while(p)
    {
        if(p&1)
            ans=ans*x%mod;
        p>>=1;
        x=x*x%mod;
    }
    return ans;
}

 

⑤快速幂取模(三阶),即求(a^(b^c))%mod

三阶和二阶的函数一样,只是输出方程有变:qpm(a,qpm(b,c,mod-1),mod);

 

⑥快速幂取模+快速乘取模(最优)

typedef long long ll;
ll qmm(ll a,ll b,ll mod)
{
    ll ans=0;
    while(b)
    {
        if(b&1)
            ans=(ans+a)%mod;
        b>>=1;
        a=(a<<1)%mod;
    }
    return ans;
}
ll qpm(ll x,ll p,ll mod)
{
    ll ans=1;
    while(p)
    {
        if(p&1)
            ans=qmm(ans,x,mod);
        p>>=1;
        x=qmm(x,x,mod);
    }
    return ans;
}
posted @ 2018-05-06 16:57  真想不出名字了  阅读(1022)  评论(0编辑  收藏  举报