擴展歐幾里得算法,是用來求形如算法
的不定方程的整數解的。spa
根據裴蜀定理,若 \(gcd(a,b) \mid c\),則必定有整數解,不然必定無解。code
設 \(d=gcd(a,b)\),顯然有 \(d \mid a,d \mid b\)。因爲 \(x,y\) 都是整數,因此 \(d \mid (ax),d \mid (by)\)。
因此若是要讓式子成立,\(c\) 必須得是 \(a,b\) 的公約數的倍數纔對。
又由於 \(x,y\) 是整數,因此 \(c\) 必須是 \(a,b\) 的最大公約數的倍數才行。
實在看不懂的話感性理解下吧awa遞歸
讓方程兩邊同除以 \(gcd(a,b)\),能夠獲得方程get
其中it
後面求特解中提到的方程均爲轉化後的方程,即後面方程中的 \(a\) 就是 \(a'\),\(b\) 就是 \(b'\)class
由歐幾里得算法可知,\(gcd(a,b)=gcd(b,a \bmod b)\)
因而,咱們能夠獲得擴展
接下來咱們就要根據 \(x',y'\) 來反推 \(x,y\)。
由於 \(gcd(a,b)=gcd(b,a \bmod b)\),因此語法
咱們把右邊的式子變形一下:gc
因此,\(x=y',y=x'-\left\lfloor\frac{a}{b}\right\rfloor y')\)。
因而咱們只要向歐幾里得算法那樣遞歸,就能獲得一組特解了。
但還有一個問題,就是遞歸邊界。
遞歸邊界顯然是 \(b=0\) 的狀況,而此時的方程就變爲:
因此此時 \(x=1\),\(y\) 是任意整數。
求解過程用代碼寫出來就是這個亞子:
ll exgcd(ll a,ll b,ll &x,ll &y) { if(b==0) { x=1; y=0;//y能夠是任意整數,這裏咱們讓他等於0也能夠 return a; } const ll m=exgcd(b,a%b,y,x); y-=(a/b)*x; return m; }
可是可是,這求的是
的解呀。不是咱們要的解。
由於咱們在轉化時讓方程兩邊都除以 \(\frac{c}{gcd(a,b)}\),因此如今要乘回來:
這裏咱們設以前求出來的通解爲 \(x_0,y_0\)。
設 \(d=gcd(a,b)\)
則通解
\(x=x_0+\frac{b}{d} \times t,y=y0-\frac{a}{d} \times t\)
t是任意整數。
爲何是這樣呢?
顯然咱們須要知足
把 \(x,y\) 拆開來:
因而就有
又由於 \(n,m\) 必須是整數,因此只有上面說的那個能夠知足要求了。
這裏指 \(x\) 是最小正整數。
當咱們求出一組特解後,最小正整數解即
上面的式子用的是 C++ 語法。 求最小正整數解慣用手法,這裏再也不累述。