淺談擴展歐幾里得算法


眾所周知,擴展歐幾里得算法(下文統稱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

那么,我們來看看Exgcd的實際應用

1.求解線性模方程

參考例題【NOIP2012】同余方程

引理:同余方程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.求解乘法逆元

參考例題【洛谷3811】乘法逆元

乘法逆元的定義:當ax≡1 (mod p)且gcd(a,p)=1時,我們稱a關於模p的逆元為x

這道題與上個例題非常相似,我們可以用同樣的方法求解。

注意,在洛谷上本題數據范圍較大,使用Exgcd總的時間復雜度為O(nlogn),不能通過本題。

求多個數的乘法逆元存在一種線性遞推的方法可以在O(n)的時間內解決,由於本博客主要講解Exgcd,所以不再贅述。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM