欧几里德算法
定义 gcd ( a , b ) \gcd(a,b) gcd(a,b) 为 a , b a,b a,b 的最大公约数
假设 gcd ( a , b ) ≡ gcd ( b , a % b ) \gcd(a,b)\equiv\gcd(b,a\%b) gcd(a,b)≡gcd(b,a%b)
设 k = a % b k=a\%b k=a%b,设 k ′ = gcd ( a , b ) k'=\gcd(a,b) k′=gcd(a,b)
则 a = x k ′ , b = y k ′ a=xk',b=yk' a=xk′,b=yk′, { x , y } ∈ [ 1 , ∞ ] \{x,y\}\in[1,∞] {x,y}∈[1,∞], x ⊥ y x\bot y x⊥y
∴ k = a % b = a − k ′ ′ b = x k ′ − k ′ ′ y k ′ = ( x − k ′ ′ y ) k ′ ∴ k=a\%b=a-k''b=xk'-k''yk'=(x-k''y)k' ∴k=a%b=a−k′′b=xk′−k′′yk′=(x−k′′y)k′
∴ k = ( x − k ′ ′ y ) k ′ ∴ k=(x-k''y)k' ∴k=(x−k′′y)k′
∵ b = y k ′ ∵ b=yk' ∵b=yk′
假设 ( x − k ′ ′ y ) (x-k''y) (x−k′′y) 与 y y y 不互质
设 y = p q , ( x − k ′ ′ y ) = p ′ q y=pq,(x-k''y)=p'q y=pq,(x−k′′y)=p′q
将 y y y 代入 ( x − k ′ ′ y ) (x-k''y) (x−k′′y)
∴ x − k ′ ′ y = x − p q k ′ ′ = p ′ q ∴ x-k''y=x-pqk''=p'q ∴x−k′′y=x−pqk′′=p′q
∴ x − p q k ′ ′ = p ′ q ∴ x-pqk''=p'q ∴x−pqk′′=p′q
∴ x = p ′ q + p q k ′ ′ ∴ x=p'q+pqk'' ∴x=p′q+pqk′′
提公因式
x = ( p ′ + p k ′ ′ ) q x=(p'+pk'')q x=(p′+pk′′)q
∵ a = x k ′ = ( p ′ + p k ′ ′ ) q k ′ ∵ a=xk'=(p'+pk'')qk' ∵a=xk′=(p′+pk′′)qk′
∵ b = y k ′ = p q k ′ ∵ b=yk'=pqk' ∵b=yk′=pqk′
∴ gcd ( a , b ) = q k ′ ∴ \gcd(a,b)=qk' ∴gcd(a,b)=qk′
与原命题不符, ∴ ( x − k ′ ′ y ) ⊥ y ∴ (x-k''y)\bot y ∴(x−k′′y)⊥y
∵ gcd ( b , a % b ) = gcd ( b , k ) = gcd ( y k ′ , ( x − k ′ ′ y ) k ′ ) ∵ \gcd(b,a\%b)=\gcd(b,k)=\gcd(yk',(x-k''y)k') ∵gcd(b,a%b)=gcd(b,k)=gcd(yk′,(x−k′′y)k′)
∵ ( x − k ′ ′ y ) ⊥ y ∵ (x-k''y) \bot y ∵(x−k′′y)⊥y
∴ gcd ( b , a % b ) ≡ k ′ ≡ gcd ( a , b ) ∴ \gcd(b,a\%b)\equiv k'\equiv \gcd(a,b) ∴gcd(b,a%b)≡k′≡gcd(a,b)
当 a % b = 0 , gcd ( a , b ) = b a\%b=0,\gcd(a,b)=b a%b=0,gcd(a,b)=b
所以就有了代码
inline int gcd(int a,int b) { return !b?a:gcd(b,a%b); }
对于斐波那契数列
gcd ( f ( n ) , f ( m ) ) = f ( gcd ( n , m ) ) \gcd(f(n),f(m))=f(\gcd(n,m)) gcd(f(n),f(m))=f(gcd(n,m))
扩展欧几里德
假设存在 { x , y } , \{x,y\}, {x,y}, 使得 gcd ( a , b ) ≡ a x + b y \gcd(a,b)\equiv ax+by gcd(a,b)≡ax+by
当 b = 0 b=0 b=0 时
gcd ( a , b ) = a , x = 1 , y = 0 \gcd(a,b)=a,x=1,y=0 gcd(a,b)=a,x=1,y=0
当 b ≠ 0 b\neq0 b=0 时
设 a x ′ + b y ′ = gcd ( a , b ) ax'+by'=\gcd(a,b) ax′+by′=gcd(a,b)
设 b x ′ ′ + ( a % b ) y ′ ′ = gcd ( b , a % b ) bx''+(a\%b)y''=\gcd(b,a\%b) bx′′+(a%b)y′′=gcd(b,a%b)
∵ a % b ≡ a − ⌊ a b ⌋ × b ∵ a\%b\equiv a-\lfloor\frac{a}{b}\rfloor\times b ∵a%b≡a−⌊ba⌋×b
∴ a x ′ + b y ′ = b x ′ ′ + ( a − ⌊ a b ⌋ × b ) y ′ ′ ∴ ax'+by'=bx''+(a-\lfloor\frac{a}{b}\rfloor\times b)y'' ∴ax′+by′=bx′′+(a−⌊ba⌋×b)y′′
∴ a x ′ + b y ′ = b x ′ ′ + a y ′ ′ − ⌊ a b ⌋ b y ′ ′ ∴ ax'+by'=bx''+ay''-\lfloor\frac{a}{b}\rfloor by'' ∴ax′+by′=bx′′+ay′′−⌊ba⌋by′′
∴ a x ′ + b y ′ = a y ′ ′ + b ( x ′ ′ − ⌊ a b ⌋ y ′ ′ ) ∴ ax'+by'=ay''+b(x''-\lfloor\frac{a}{b}\rfloor y'') ∴ax′+by′=ay′′+b(x′′−⌊ba⌋y′′)
∴ x ′ = y ′ ′ , y ′ = ( x ′ ′ − ⌊ a b ⌋ y ′ ′ ) ∴ x'=y'',y'=(x''-\lfloor\frac{a}{b}\rfloor y'') ∴x′=y′′,y′=(x′′−⌊ba⌋y′′)
$∵ $ 当 b = 0 b=0 b=0 时存在解
∴ ∴ ∴ 解存在
然后我们就有代码了
inline void exgcd(int a,int b) {
if(b) {
exgcd(b,a%b);
int t=x; x=y;
y=k-a/b*y;
} else y=(x=1)-1;
}
贝祖定理
定义: a x + b y = c ax+by=c ax+by=c ,满足 { x , y } ∈ [ 1 , ∞ ] \{x,y\}\in[1,∞] {x,y}∈[1,∞],且 gcd ( a , b ) ∣ c \gcd(a,b)|c gcd(a,b)∣c
设 s = gcd ( a , b ) s=\gcd(a,b) s=gcd(a,b),则 s ∣ a s|a s∣a 且 s ∣ b s|b s∣b
且 s ∣ a x s|ax s∣ax 且 s ∣ b y s|by s∣by
设 k ′ ∈ [ 1 , ∞ ] k'\in[1,∞] k′∈[1,∞]
则 c = gcd ( a , b ) × k ′ c=\gcd(a,b)\times k' c=gcd(a,b)×k′
∴ gcd ( a , b ) ∣ c ∴ \gcd(a,b)|c ∴gcd(a,b)∣c 成立
扩展欧几里德解不定方程
对于不定方程 a x + b y = c ax+by=c ax+by=c,设 k ′ = gcd ( a , b ) k'=\gcd(a,b) k′=gcd(a,b)
∵ ∵ ∵ 存在 { x , y } \{x,y\} {x,y} 使得 gcd ( a , b ) ≡ a x + b y ≡ k ′ \gcd(a,b) \equiv ax+by \equiv k' gcd(a,b)≡ax+by≡k′
当 c % k ′ ≠ 0 c\%k'\neq 0 c%k′=0 无解
当 c % k ′ = 0 c\%k'=0 c%k′=0
可用 exgcd \text{exgcd} exgcd 算出 gcd ( a , b ) = a x + b y \gcd(a,b)=ax+by gcd(a,b)=ax+by,即 a x + b y = k ′ ax+by=k' ax+by=k′ 的一组解
解得 x = x 0 , y = y 0 x=x_0,y=y_0 x=x0,y=y0
∴ x 0 × c k ′ , y 0 × c k ′ ∴ x_0\times \frac{c}{k'},y_0\times \frac{c}{k'} ∴x0×k′c,y0×k′c
∴ x = x 0 × c k ′ × k ′ ′ , y = y 0 × c k ′ × k ′ ′ ∴ x=x_0\times\frac{c}{k'}\times k'',y=y_0\times\frac{c}{k'}\times k'' ∴x=x0×k′c×k′′,y=y0×k′c×k′′
∴ a c k ′ ′ x 0 k ′ + b c k ′ ′ y 0 k ′ = c ∴ \frac{ack''x_0}{k'}+\frac{bck''y_0}{k'}=c ∴k′ack′′x0+k′bck′′y0=c
∴ a c k ′ ′ x 0 + b c k ′ ′ y 0 = c k ′ ∴ ack''x_0+bck''y_0=ck' ∴ack′′x0+bck′′y0=ck′
∴ ( a x 0 + b y 0 ) c k ′ ′ = c k ′ ∴ (ax_0+by_0)ck''=ck' ∴(ax0+by0)ck′′=ck′
∴ c k ′ k ′ ′ = c k ′ ∴ ck'k''=ck' ∴ck′k′′=ck′
∴ k ′ ′ = 1 ∴ k''=1 ∴k′′=1
∴ x = x 0 × c k ′ , y = y 0 × c k ′ ∴ x=x_0\times \frac{c}{k'},y=y_0\times \frac{c}{k'} ∴x=x0×k′c,y=y0×k′c
∴ a x 0 × c k ′ + b y 0 × c k ′ = c ∴ ax_0\times\frac{c}{k'}+by_0\times\frac{c}{k'}=c ∴ax0×k′c+by0×k′c=c
∴ ( a x 0 + b y 0 ) × c k ′ = c ∴ (ax_0+by_0)\times \frac{c}{k'}=c ∴(ax0+by0)×k′c=c
∴ a x 0 + b y 0 = k ′ ∴ ax_0+by_0=k' ∴ax0+by0=k′
所以此式恒等成立
扩展欧几里德解同余方程
对于同余方程 a x ≡ c m o d b ax\equiv c \mod b ax≡cmodb
∴ a x − c ≡ 0 m o d b ∴ ax-c\equiv 0 \mod b ∴ax−c≡0modb
∴ a x + b y ≡ c ∴ ax+by\equiv c ∴ax+by≡c
所以,只要求 exgcd \text{exgcd} exgcd 即可
乘法逆元
通常用于求
a b ( m o d p ) \frac{a}{b} \pmod p ba(modp)
若
a × x ≡ 1 ( m o d p ) a\times x \equiv 1 \pmod p a×x≡1(modp)
且 a a a 与 x x x 互质,则可称 x x x 为 a a a 的逆元,也称 x x x 为 a a a 的倒数
对于
a b ( m o d p ) \frac{a}{b} \pmod p ba(modp)
只需求出
( 1 b ( m o d p ) ) × a (\frac{1}{b} \pmod p)\times a (b1(modp))×a
也就是求出 b b b 的逆元再乘上 a a a
拓展欧几里德解乘法逆元
利用拓展欧几里德解同余方程 a x ≡ c ( m o d p ) ax\equiv c \pmod p ax≡c(modp) 时 c = 1 c=1 c=1 的情况
也就是转换为 a x + b y ≡ 1 ax+by\equiv 1 ax+by≡1 的情况
然后用 exgcd \text{exgcd} exgcd 求解
快速幂解乘法逆元
通过费马小定理可知, ∀ a ∈ [ 1 , ∞ ] \forall a \in[1,∞] ∀a∈[1,∞] 与素数 p p p
有 a p − 1 ≡ 1 ( m o d p ) a^{p-1}\equiv 1 \pmod p ap−1≡1(modp)
有 a x ≡ 1 ( m o d p ) ax\equiv 1 \pmod p ax≡1(modp)
所以有 a p − 1 ≡ a x ( m o d p ) a^{p-1}\equiv ax \pmod p ap−1≡ax(modp)
所以有 a p − 2 ≡ x ( m o d p ) a^{p-2}\equiv x \pmod p ap−2≡x(modp)
只要用快速幂求出 a p − 2 ( m o d p ) a^{p-2} \pmod p ap−2(modp) 的值就行了
线性乘法逆元
对于求一连串数字 ( m o d p ) \pmod p (modp) 的逆元,上面的方法就显得慢
考虑逆元之间的递推关系
首先我们有 1 − 1 ≡ 1 m o d p 1^{-1}\equiv 1 \mod p 1−1≡1modp
不妨设 p = k × i + r p=k\times i + r p=k×i+r,也就是 k = ⌊ p i ⌋ k=\lfloor\frac{p}{i}\rfloor k=⌊ip⌋
则 k × i + r ≡ 0 ( m o d p ) k\times i + r \equiv 0 \pmod p k×i+r≡0(modp)
乘上 i − 1 × r − 1 i^{-1}\times r^{-1} i−1×r−1
得
k × r − 1 + i − 1 ≡ 0 ( m o d p ) k\times r^{-1}+i^{-1}\equiv 0 \pmod p k×r−1+i−1≡0(modp)
i − 1 ≡ − k × r − 1 ( m o d p ) i^{-1}\equiv-k\times r^{-1} \pmod p i−1≡−k×r−1(modp)
i − 1 ≡ − ⌊ p i ⌋ × r − 1 ( m o d p ) i^{-1}\equiv-\lfloor\frac{p}{i}\rfloor\times r^{-1} \pmod p i−1≡−⌊ip⌋×r−1(modp)
i − 1 ≡ − ⌊ p i ⌋ × ( p ( m o d i ) ) − 1 ( m o d p ) i^{-1}\equiv-\lfloor\frac{p}{i}\rfloor\times(p \pmod i)^{-1} \pmod p i−1≡−⌊ip⌋×(p(modi))−1(modp)
然后我们就有代码了
ans[1]=1;
for(int i=1;i<p;i++) ans[i]=(p-p/i)*ans[p%i]%p;
阶乘逆元
我们有
a n s [ i + 1 ] = 1 ( i + 1 ) ! ans[i+1]=\frac{1}{(i+1)!} ans[i+1]=(i+1)!1
a n s [ i + 1 ] × ( i + 1 ) = i + 1 ( i + 1 ) ! = 1 i = a n s [ i ] ans[i+1]\times (i+1)=\frac{i+1}{(i+1)!}=\frac{1}{i}=ans[i] ans[i+1]×(i+1)=(i+1)!i+1=i1=ans[i]
a n s [ i ] = a n s [ i + 1 ] × ( i + 1 ) ans[i]=ans[i+1]\times (i+1) ans[i]=ans[i+1]×(i+1)
所以就可以从后往前求出所有逆元