同餘問題(一)——擴展歐幾里得exgcd

前言

擴展歐幾里得算法是一個很好的解決同餘問題的算法,非常實用。


歐幾里得算法

簡介

歐幾里得算法,又稱輾轉相除法。

主要用途

求最大公因數gcdgcd

公式

gcd(a,b)=gcd(b,a%b)gcd(a,b)=gcd(b,a\%b)

公式證明

aa可以表示成a=kb+a%ba=kb+a\%bkk爲自然數)。

假設gga,ba,b的一個公約數,則有ga,gbg|a, g|b

a%b=akb\because a\%b=a-kb

g(a%b),g\therefore g|(a\%b),\therefore gb,a%bb,a\%b的公約數。

綜上所述,a,ba,bb,a%bb,a\%b的公約數是一樣的,其gcdgcd也必然相等。

代碼實現
inline int gcd(int x,int y) {return y?gcd(y,x%y):x;}

擴展歐幾里得算法

簡介

擴展歐幾里得建立於歐幾里得算法的基礎上。(該算法的升級版 徐xgcd有待XuRuiYang奆佬發明)

主要用途

對於已知a,b求解x,y使其滿足ax+by=gcd(a,b)。

解法

我們可以對(a,b)(a,b)不斷輾轉相除。

根據歐幾里得算法,最後剩下的兩個數一定爲(gcd(a,b),0)(gcd(a,b),0)

顯然,此時x=1,y=0x=1,y=0是原式的一組解。

現在,我們需要考慮,若已知(b,a%b)(b,a\%b)的解,如何推出(a,b)(a,b)的解。

x0,y0x_0,y_0(b,a%b)(b,a\%b)的一組解,則x0b+y0(a%b)=gcd(b,a%b)x_0·b+y_0(a\%b)=gcd(b,a\%b)

將這個式子轉化一下,可以得到x0b+y0(aabb)=gcd(a,b)x_0·b+y_0(a-\lfloor\frac ab\rfloor*b)=gcd(a,b)

去括號,得x0b+y0a(y0ab)b=gcd(a,b)x_0·b+y_0·a-(y_0·\lfloor\frac ab\rfloor)·b=gcd(a,b)

合併同類項,得y0a+(x0y0ab)b=gcd(a,b)y_0·a+(x_0-y_0·\lfloor\frac ab\rfloor)·b=gcd(a,b)

x=y0,y=x0y0ab\therefore x=y_0,y=x_0-y_0·\lfloor\frac ab\rfloor是原式的一組解。

遞歸即可。

代碼實現
inline int exgcd(int x,int y,int &s1,int &s2)
{
	if(!y) return s1=1,s2=0,x;
	register int res=exgcd(y,x%y,s2,s1);
	return s2-=x/y*s1,res; 
}

擴歐的典型應用:求乘法逆元

LinkLink

乘法逆元 詳見博客 淺談乘法逆元的三種解法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章