1. 程式人生 > >基礎數論——EXGCD

基礎數論——EXGCD

# 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.$ $皆さん、さよ