基礎數論——EXGCD
阿新 • • 發佈:2020-06-03
# 1.前言 #
$皆さん、こんにちは。$今天我們來講 $EXGCD$ 。(擴充套件歐幾里得)
既然是擴充套件嘛,那肯定有不擴充套件的,也就是 $GCD$ 。
我們都知道 $GCD$ 怎麼寫:
```cpp
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.程式碼 #
```cpp
#include
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.$
$皆さん、さよ