逆元的几个求法。
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×bp−2modp ( 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=(p−ip)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]=(p−ip)×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[i−1]×inv[i]modp