逆元的几个求法。

1. 1. 1.扩展欧几里得 e x g c d exgcd exgcd

void exgcd(int a,int b,int &x,int &y){
    if(!b) x=1,y=0;
    else{
        exgcd(b,a%b,x,y);
        int tmp=x;
        x=y;
        y=tmp-(a/b)*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;//y1赋给x,x1赋给y,y=x1-(a/b)*y1 -> y=y-a/b*x;
}

2.费马小定理。

( a b   m o d   p ) = a × b p − 2   m o d   p (\dfrac{a}{b}\bmod p)=a\times b^{p-2}\bmod p (bamodp)=a×bp2modp ( p p p为质数, b b b不是 p p p的倍数)

3.线性递推。

i n v [ 1 ] = 1 ( m o d p ) inv[1]=1\pmod{p} inv[1]=1(modp) ,令 p = k × i + r p=k\times i+r p=k×i+r

即: k = p / i , r = p   m o d   i k=p/i,r=p\bmod i k=p/i,r=pmodi (1)

k × i + r = 0 ( m o d p ) k\times i+r=0\pmod{p} k×i+r=0(modp)

等式两边同乘 i n v [ i ] , i n v [ r ] inv[i],inv[r] inv[i],inv[r]

k × i n v [ r ] + i n v [ i ] = 0 ( m o d p ) k\times inv[r]+inv[i]=0\pmod{p} k×inv[r]+inv[i]=0(modp)

i n v [ i ] = − k × i n v [ r ] ( m o d p ) inv[i]=-k\times inv[r]\pmod{p} inv[i]=k×inv[r](modp)

将(1)代入得: i n v [ i ] = − p i × i n v [ ( p   m o d   i ) ]   m o d   p inv[i]=-\dfrac{p}{i}\times inv[(p\bmod i)]\bmod{p} inv[i]=ip×inv[(pmodi)]modp

因为 − p i m o d   p = ( p − p i ) m o d   p -\dfrac{p}{i}mod\ p=(p-\dfrac{p}{i})mod\ p ipmod p=(pip)mod p (最小正整数解)

综上 i n v [ i ] = ( p − p i ) × i n v [ ( p   m o d   i ) ] m o d   p inv[i]=(p-\dfrac{p}{i})\times inv[(p\ mod\ i)] mod\ p inv[i]=(pip)×inv[(p mod i)]mod p

这样就可以进行递推了。

4.阶乘逆元。

f a c i n v [ i + 1 ] = 1 ( i + 1 ) ! facinv[i+1]=\dfrac{1}{(i+1)!} facinv[i+1]=(i+1)1

f a c i n v [ i + 1 ] × ( i + 1 ) = 1 i ! = f a c i n v [ i ] facinv[i+1]\times(i+1)=\dfrac{1}{i!}=facinv[i] facinv[i+1]×(i+1)=i!1=facinv[i]

因此可以从后往前递推。也是线性的。

也可以从前往后推,不过要先求出 i n v [ i ] inv[i] inv[i]

f a c i n v [ i ] = f a c i n v [ i − 1 ] × i n v [ i ]   m o d   p facinv[i]=facinv[i-1]\times inv[i]\bmod p facinv[i]=facinv[i1]×inv[i]modp