跳转至

乘法逆元

若**\(ax≡1 \pmod f\), 则称a(关于1)模f的乘法逆元为x。也可表示为\(ax≡1\pmod f\)**。

当a与f互素时,a关于模f的乘法逆元有解。如果**不互素,则无解**。如果f为素数,则从1到f-1的任意数都与f互素,即在1到f-1之间都恰好有一个关于模f的乘法逆元。

欧几里德算法

其求法可用**欧几里德算法**: exgcd算法求d关于模f的乘法逆元d-1 ,即 d* d-1 mod f = 1 它适用于所有情况下求解逆元!

伪代码

 (X1X2X3) := (10f) (Y1Y2Y3) := (01d)
 if (Y3=0) then return d-1 = null //无逆元
 if (Y3=1) then return d-1 = Y2 //Y2为逆元
 Q := X3 div Y3 //整除
 (T1T2T3) := (X1 - QY1X2 - QY2X3 - Q*Y3)
 (X1X2X3) := (Y1Y2Y3)
 (Y1Y2Y3) := (T1T2T3)
 goto 2

代码

int x,p,a,n,y;
void exgcd(int a,int b,int &x,int &y){
    if(!b)x=1,y=0;
    else exgcd(b,a%b,y,x),y-=a/b*x;
}
signed main() {
    scanf("%d%d",&n,&p);
    for(int i=1;i<=n;i++){
        exgcd(i,p,x,y);
        x=(x%p+p)%p;
        printf("%d\n",x);
    }
    return 0;
}

费马小定理

求此算法还可以使用**费马小定理** 只不过局限性比较大,要求模数是素数 \(a^{p-1} =1\pmod p\) p要求是素数 那么\(a^{p-2}\)就是a的乘法逆元

线性递推

\(inv[i]=(p−⌊\frac{i}{p}​⌋×inv[p\%i]\%p)\%p\)

inv[1]=1;
for(int i=2;i<=n;i++){
    inv[i]=(p-p/i)*inv[p%i]%p;

分数取模

通常我们要输出分数时,题目会要求我们对分数进行取模后输出。此时我们将分数的分母变成逆元形式乘上分子即可。

不好维护分母和分子?对模数取模的分数还有一个很好的性质:

要把两个分数相加,就直接把两个分数(取模后)相加即可!相乘也是一样。