记录:扩展欧几里得算法
本文遵循 CC BY-NC-ND 4.0 协议,作者: U•ェ•*U \texttt{U•ェ•*U} U•ェ•*U,转载请获得作者授权。
前置知识
裴蜀定理/贝祖定理:若 a , b a,b a,b 是整数,且 gcd ( a , b ) = d \gcd(a,b)=d gcd(a,b)=d,那么对于任意整数 x , y x,y x,y, a × x + b × y = k a\times x + b\times y = k a×x+b×y=k 中的 k k k 一定是 d d d 的倍数。(特别地,如果 a , b a,b a,b 是整数,那么一定存在整数 x , y x,y x,y 使得 a × x + b × y = gcd ( a , b ) a\times x + b\times y = \gcd(a,b) a×x+b×y=gcd(a,b))
引入
引入扩展欧几里得算法,可用于求解以下几种问题:
- 给定两个非零的整数 a a a 和 b b b,求一组整数解 ( x , y ) (x,y) (x,y) 使得 a × x + b × y = gcd ( a , b ) a\times x + b\times y = \gcd(a,b) a×x+b×y=gcd(a,b) 成立,其中 gcd ( a , b ) \gcd(a,b) gcd(a,b) 表示 a a a 和 b b b 的最大公约数。
- 逆元
从欧几里得算法推导:
gcd ( x , y ) → gcd ( y , x m o d y ) ⇓ ∀ x n = 1 , y n = 0 ∀ a × x 1 + b × x 1 = gcd ⇓ ∀ b × x 2 + ( a m o d b ) × y 2 = gcd ∀ a × x 1 + b × x 1 = b × x 2 + ( a m o d b ) × y 2 ∀ a × x 1 + b × y 1 = a × y 1 + b × ( x 2 × a b × y 2 ) \gcd(x, y) \to \gcd(y, x \mod y) \\ \Downarrow \\ \forall x_{n} = 1, y_{n} = 0 \\ \\ \forall a\times x_1 + b \times x_1 = \gcd \\ \Downarrow \\ \forall b\times x_2 + (a\mod b)\times y_2 = \gcd \\ \forall a\times x_1 + b \times x_1 = b\times x_2 + (a\mod b)\times y_2 \\ \forall a\times x_1 + b \times y_1 = a\times y_1 + b\times (x_2\times \frac{a}{b}\times y_2) gcd(x,y)→gcd(y,xmody)⇓∀xn=1,yn=0∀a×x1+b×x1=gcd⇓∀b×x2+(amodb)×y2=gcd∀a×x1+b×x1=b×x2+(amodb)×y2∀a×x1+b×y1=a×y1+b×(x2×ba×y2)
于是反推出原来的值( x 1 , y 1 x_1, y_1 x1,y1):
void exgcd(int a, int b, int &x, int &y) {if (a % b == 0) x = 0, y = 1;else {exgcd(b, a % b, y, x);y -= a / b * x;}
}
证明:
[TODO]
求同余式
对两个整数 a , b a, b a,b,如果它们除以 d d d 的余数相同,则称它们模 d d d 同余,记作 a ≡ b ( m o d d ) a\equiv b (\mod d) a≡b(modd)。
在同余号两侧同时加、减、乘任意整数,同余式仍成立。
我们设一个同余式 a x ≡ c ( m o d m ) ax\equiv c (\mod m) ax≡c(modm),那么可以分讨求解:
- 若 c m o d gcd ( a , m ) ≠ 0 c\mod \gcd(a,m) \neq 0 cmodgcd(a,m)=0,则同余方程 a x ≡ c ( m o d m ) ax\equiv c(\mod\ m) ax≡c(mod m) 无解。
- 若 c m o d gcd ( a , m ) = 0 c\mod \gcd(a, m) = 0 cmodgcd(a,m)=0,则同余方程的解为 $x’ = x + \frac{\gcd(a, m)}{m}\times \mathbb{N} $。
求逆元
对任意给定的 x x x 和 p p p,显然 x × x − 1 ≡ 1 ( m o d p ) x \times x ^ {-1} \equiv 1 (\mod p) x×x−1≡1(modp)。可以利用
这个式子计算 x − 1 x ^ {-1} x−1。
其中 x x x 和 p p p 是已知量,所以上式是一个不定方程, x − 1 x ^ {−1} x−1 和 k k k
是变量。用 exgcd \texttt{exgcd} exgcd 求解可以得到 x − 1 x ^ {−1} x−1。
C++ \texttt{C++} C++ 代码(线性求逆元):
int n, p, inv[3000010];
signed main() {cin >> n >> p;inv[1] = 1;cout << 1 << endl;for (int i = 2; i <= n; i ++) {inv[i] = (int)(p - p / i) * inv[p % i] % p;printf("%lld\n", inv[i]);}return 0;
}