擴展歐幾里得算法(exgcd)

擴展歐幾里得算法,是用來求形如算法

\[ax+by=c \]

的不定方程的整數解的。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

\[a'x+b'y=c' \]

其中it

\[a'=a \times \frac{gcd(a,b)}{c},b'=b \times \frac{gcd(a,b)}{c},c'=c \times \frac{gcd(a,b)}{c}=gcd(a,b) \]

後面求特解中提到的方程均爲轉化後的方程,即後面方程中的 \(a\) 就是 \(a'\)\(b\) 就是 \(b'\)class

求解

求特解

由歐幾里得算法可知,\(gcd(a,b)=gcd(b,a \bmod b)\)
因而,咱們能夠獲得擴展

\[bx'+(a \bmod b)y'=gcd(b,a \bmod b) \]

接下來咱們就要根據 \(x',y'\) 來反推 \(x,y\)
由於 \(gcd(a,b)=gcd(b,a \bmod b)\),因此語法

\[ax+by=bx'+(a \bmod b)y' \]

咱們把右邊的式子變形一下:gc

\[bx'+(a \bmod b)y' \]

\[=(a-b\left\lfloor\frac{a}{b}\right\rfloor)y'+bx' \]

\[=ay'+bx'-b\left\lfloor\frac{a}{b}\right\rfloor y' \]

\[= ay'+b(x'-\left\lfloor\frac{a}{b}\right\rfloor y') \]

因此,\(x=y',y=x'-\left\lfloor\frac{a}{b}\right\rfloor y')\)
因而咱們只要向歐幾里得算法那樣遞歸,就能獲得一組特解了。
但還有一個問題,就是遞歸邊界。
遞歸邊界顯然是 \(b=0\) 的狀況,而此時的方程就變爲:

\[ax+by=ax=gcd(a,0)=a \]

因此此時 \(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;
}

可是可是,這求的是

\[ax+by=gcd(a,b) \]

的解呀。不是咱們要的解。
由於咱們在轉化時讓方程兩邊都除以 \(\frac{c}{gcd(a,b)}\),因此如今要乘回來:

\[x=x \times \frac{c}{gcd(a,b)},y=y \times \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是任意整數。
爲何是這樣呢?
顯然咱們須要知足

\[ax+by=c \]

\(x,y\) 拆開來:

\[a(x_0+n)+b(y_0-m)=c \]

因而就有

\[an-bm=0 \]

又由於 \(n,m\) 必須是整數,因此只有上面說的那個能夠知足要求了。

求最小正整數解

這裏指 \(x\) 是最小正整數。
當咱們求出一組特解後,最小正整數解即

\[x=(x_0\%\frac{b}{d}+\frac{b}{d})\%\frac{b}{d},y=(c-ax)/b \]

上面的式子用的是 C++ 語法。 求最小正整數解慣用手法,這裏再也不累述。

相關文章
相關標籤/搜索