乘法逆元(学习笔记)

蒟蒻最近碰到了好多对分数取模的题,一脸懵逼(模不是只有整数之间才有的运算么)

定义

若整数b,m互质,并且b整除a(a被b整除,即a是b的整数倍),则存在一个整数x,使得(a/b≡a*x)(mod m),则称x为b的模m的乘法逆元,记为(b^{-1})(mod m);

推理:

因为(a/b=a*b^{-1}=a/b*b*b^{-1})

所以(a/b≡a*b^{-1}≡a/b*b*b^{-1})(mod m)

所以(b*b^{-1}≡1)(mod m)

求法

其实求乘法逆元的方法有很多,就看哪种好用,注意别搞混了就行;

方法一 扩展欧几里得

(a*x≡1)(mod p)可以等价的转化为(a*x-p*y=1)

然后套用exgcd模板解方程,并检查gcd(a,p)是否等于1.

如果gcd(a,p)=1,把x调整到1~p−1的范围内即可.

ll exgcd(ll a,ll b,LL &x,LL &y) {
    if(b==0){x=1;y=0;return a;}
    ll GCD=exgcd(b,a%b,x,y);
    ll z=x;
    x=y;y=z-a/b*y;
    return GCD;
}//这个函数是扩展欧几里得算法的模板
ll Exgcd(ll a,ll mod){
    ll x,y;
    ll d=exgcd(a,mod,x,y);
    if(d==1) return(x%mod+mod)%mod;
    return -1;
}

方法二 费马小定理

如果p是质数,并且b<p,根据费马小定理(若p是质数,则对于任意正整数b,有(b^p≡b)(mod p))可得(b^{p-1}≡1)(mod p),相当于(b*b^{p-2}≡1)(mod p),所以,当模数p为质数时,(b^{p-2})就是b的乘法逆元;

但如果只是保证b,p互质,那么乘法逆元可通过求解同余方程(b*x≡1)(mod p)得到;

ll feima(ll a,ll mod){
    return quickpow(a,mod-2,mod);
} //quickpow快速幂模板我就不讲了啊

方法三 欧拉定理

(a^{φ(p)}≡1)(mod p)得(a^{φ(p)-1})是a的逆元

太懒,在这里不讲欧拉函数和欧拉定理了

https://www.cnblogs.com/PPXppx/p/9877833.html

方法四 递推

通过线性递推我们可以在O(N)的时间内求出1~n在模p意义下的乘法逆元;

以上几种方法可能在求某一个值的乘法逆元时很方便,但如果要求1~n中的每一个数的乘法逆元,就不得不用到这个递推了;

这里直接给出递推公式,反正我这么蒻,也不会证明,也不会理解,就直接背公式了;

void ditui(ll mod){
    inv[1]=1;
    for(int i=2;i<=n;i++) {
		inv[i]=(mod-mod/i)*inv[mod%i]%mod;
    }
}

扩展:做组合数学时,我们会要求阶乘的逆元,也可以在O(N)的时间递推;

jc[0]=1;
for(int i=1;i<=N;i++) 
    jc[i]=(jc[i-1]*i)%mod; 
inv_jc[N]=quickpow(jc[N],mod-2);
for(int i=N-1;i>=0;i--) 
    inv_jc[i]=(inv_jc[i+1]*(i+1))%mod;
原文地址:https://www.cnblogs.com/PPXppx/p/9889288.html