眾所周知,擴展歐幾里得算法(下文統稱Exgcd)能求解二元一次方程的整數解,乘法逆元、線性模方程等。本文我將簡單的介紹該算法。
形如ax+by=gcd(a,b) 的方程,我們可以用Exgcd求出其最小整數解。我們考慮如何求解。
當b=0時,方程右邊的值為a,那么顯然可得x=1,y=0。
現在假設當前方程為ax1+by1=gcd(a,b),我們已經求得方程bx2+a%by2=gcd(a,b)的解為x2,y2,我們考慮通過x2,y2推出x1,y1的值、
解法如下:
因此,我們在gcd算法的代碼上稍加改動,即可完成Exgcd的代碼實現。
Exgcd算法的時間復雜度與gcd相等,最壞情況下近似於O(logn)

1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 int exgcd(int a, int b, int &x, int &y) { 5 if (b == 0) { 6 x = 1; y = 0; 7 return a; 8 } 9 int gcd = exgcd(b, a % b, x, y); 10 int x2 = x, y2 = y; 11 x = y2; 12 y = x2 - (a / b) * y2; 13 return gcd; 14 } 15 int main() { 16 int a, b, x, y; 17 scanf("%d%d", &a, &b); 18 exgcd(a, b, x, y); 19 printf("%d %d\n", x, y); 20 return 0; 21 }
那么,我們來看看Exgcd的實際應用
1.求解線性模方程
引理:同余方程ax≡b(mod p)有解,當且僅當gcd(a,p)|b,在本題中,b=1,即gcd(a,p)=1;
變形,得到方程ax-py=gcd(a,p),這是Exgcd的一般形式,我們套用算法即可。
注意,本題要求出方程的最小正整數解,而Exgcd求出的是最小整數解,所以我們將答案加上p在mod p即可。
代碼略
2.求解乘法逆元
乘法逆元的定義:當ax≡1 (mod p)且gcd(a,p)=1時,我們稱a關於模p的逆元為x
這道題與上個例題非常相似,我們可以用同樣的方法求解。
注意,在洛谷上本題數據范圍較大,使用Exgcd總的時間復雜度為O(nlogn),不能通過本題。
求多個數的乘法逆元存在一種線性遞推的方法可以在O(n)的時間內解決,由於本博客主要講解Exgcd,所以不再贅述。