1.前言
\(皆さん、こんにちは。\)今天我們來講 \(EXGCD\) 。(擴充套件歐幾里得)
既然是擴充套件嘛,那肯定有不擴充套件的,也就是 \(GCD\) 。
我們都知道 \(GCD\) 怎麼寫:
ll GCD(ll X,ll Y){ return Y==0?X:GCD(Y,X%Y);}
然後今天就要講它的升級版: \(EXGCD\) 。
2.講解
上面一段就是 \(GCD\) 的寫法,它能夠快速解決最大公約數問題。
那麼 \(EXGCD\) 就是要解決下面的這個問題:
\(a\times q\equiv c \pmod{p}\)
已知整數 \(q\) , \(p\) , \(c\) ,求整數 \(a\) 。
那麼我們現在把問題轉化一下,顯然我們不可能直接對這個問題進行求解。
\(a\times q + b\times p = c\)
模 \(p\) 相當於就是加上一些 \(p\) 或者減去一些,我們用一個未知量 \(b\) 來表示 \(p\) 的數量。但相較於第一個式子,這個式子更加簡潔。
所以現在我們就是要求出 \(a\) 和 \(b\) 的值。
由於是模 \(p\) 意義下的,所以我們令 \(a\) , \(b\) 都是非負整數。
我們設 \(d=gcd(q,p)\) ,那麼可得以下式子:
\(d \times \dfrac{q}{d} \times a + d \times \dfrac{p}{d} \times b = d \times \dfrac{c}{d}\)
由於 \(gcd(q,p) \mid q\) 且 \(gcd(q,p) \mid p\) ,那麼 \(\dfrac{q}{d}\) 和 \(\dfrac{p}{d}\) 就是整數,那麼 \(\dfrac{c}{d}\) 也是整數,所以 \(gcd(q,p) \mid c\) 。
那麼如果我們求解了以下式子:
\(x\times q + y\times p = gcd(q,p)\)
然後令 \(x\) 乘上 \(\dfrac{c}{gcd(q,p)}\) 就是 \(a\) 的值了。
我們設 \(x_1\) , \(y_1\) 為 \(gcd(q,p)\) 的解。
\(x_1 \times q + y_1 \times p = gcd(q,p)\) ①
然後設 \(x_2\) , \(y_2\) 為 \(gcd(p,q\ mod\ p)\) 的解。
\(x_2 \times p + y_2 \times (q\ mod\ p) = gcd(p,q\ mod\ p)\)
顯然 \(gcd(p,q\ mod\ p)\) 和 \(gcd(q,p)\) 是相等的,都是求 \(p\) 和 \(q\) 的最大公約數,所以得:
\(x_2 \times p + y_2 \times (q\ mod\ p) = gcd(q,p)\) ②
接下來把 ③ 式的 “\(q\ mod\ p\)” 展開得:
\(x_2 \times p + y_2 \times q - y_2 \times \left\lfloor\dfrac{q}{p}\right\rfloor \times p = gcd(q,p)\) ③
由 ①、③ 二式得, \(x_1=y_2\) 、 \(y_1=x_2-y_2 \times \left\lfloor\dfrac{q}{p}\right\rfloor\) 。
所以我們發現, \(p\) 和 \(q\) 的解是由 \(q\) 和 \((p\ mod\ q)\) 推過來的,所以我們可以在求 \(q\) 和 \(p\) 的最大公約數遞迴返回的過程中求解 \(x\) 和 \(y\) 。
當 \(p\) 為 \(0\) 的時候 \(q\) 為最大公約數,此時的 \(x=1\) , \(y=0\) 。
這樣 \(EXGCD\) 就講完了。
3.程式碼
#include<bits/stdc++.h>
using namespace std;
long long Q,P,X,Y;
long long Exgcd(long long Q,long long P,long long &X1,long long &Y1){
if(!P){ X1=1;Y1=0; return Q;}
long long X2,Y2,D=Exgcd(P,Q%P,X2,Y2);
X1=Y2;Y1=X2-(Q/P)*Y2;
return D;
}
int main(){
scanf("%lld%lld",&Q,&P);
Exgcd(Q,P,X,Y);
while(X<0) X=X+P;
printf("%lld\n",X%P);
return 0;
}
\(Thanks for Watch.\)
\(皆さん、さよなら。\)