乘法逆元计算模板

乘法逆元,就是有ab ≡  1 mod p,则b就是mod p意义下乘法的逆元,即b=inv(a)。

逆元的意义就是在模意义下,即剩余系中,除法是没有封闭性的,很有可能造成溢出,所以用

乘法逆元代替除法。因为本人是蒟蒻,这里就记一下求逆元的方法和模板了。

1.递推求乘法逆元。

在O(n)时间内可以推出1~n 在模p意义下的逆元。方法如下:

乘法逆元计算模板_第1张图片

所以线性递推式为

inv[i]=(mod-mod/i)*inv[mod%i]%mod;

如何利用呢?我们可以利用这个求组合数在mod意义下的值,函数如下:

const ll mod=1e9+7;
const ll maxn=1e5+1;

ll f[maxn]={1,1};
ll f0[maxn]={1,1};
ll inv[maxn]={1,1};

void init()
{
    for(int i=2;i<=maxn;i++)
    {
        //阶乘数
        f[i]=f[i-1]*i%mod;
        //i在mod意义下的逆元
        f0[i]=(mod-mod/i)*f0[mod%i]%mod;
        //阶乘逆元
        inv[i]=inv[i-1]*f0[i]%mod;
    }
}

//求阶乘数C(a,b)在mod意义下的值
ll C(ll a,ll b)
{    
    return f[b]*inv[a]%mod*inv[b-a]%mod;
}

是不是清晰明了?这儿有道模板题,代码补全就能提交~

牛客国庆集训day3——H

2.扩展欧几里得求逆元

ax≡1(modp)可以等价的转化为ax−py=1
然后套用exgcd解方程,并检查gcd(a,p)是否等于1
如果gcd(a,p)=1,把x调整到1~p−1即可
复杂度O(log n) 。

3.费马小定理

由于a^{^{p-1}}\equiv 1(mod p),所以a*a^{p-2}\equiv 1 (mod p),所以i的逆元就是模p意义下的i^{^{p-2}}

inv(i)=i^{p-2} mod p,所以递推就行。

4.欧拉定理

a^{\varphi (p)}\equiv 1 (mod p),所以a^{\varphi (p)-1}就是a的逆元。

模板代码如下,参考于大佬:https://blog.csdn.net/sdfzchy/article/details/76098066

#include
#include
#include
#include
using namespace std;
#define LL long long
int inv[1000010];

LL ksm(LL a,LL b,LL mod)
{
    int ans=1;
    while(b)
    {
        if(b&1) ans=(ans*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return ans;
} 

LL exgcd(LL a,LL b,LL &x,LL &y)
{
    if(!b)
    {
        x=1;
        y=0;
        return a;
    }
    LL GCD=exgcd(b,a%b,x,y);
    LL tmp=x;
    x=y;
    y=tmp-a/b*y;
    return GCD;
}

LL inv1(LL a,LL mod)//扩展欧几里得求逆元 
{
    LL x,y;
    LL d=exgcd(a,mod,x,y);
    if(d==1) return (x%mod+mod)%mod;
    return -1;
}

LL inv2(LL a,LL mod)//费马小定理
{
    return ksm(a,mod-2,mod);
} 

void inv3(LL mod)//线性递推求逆元 
{
    inv[1]=1;
    for(int i=2;i<=mod-1;i++)
    {
        inv[i]=(mod-mod/i)*inv[mod%i]%mod;
        cout<>n>>mod)
    {
        cout<

 

你可能感兴趣的:(数论)