前言
擴展歐幾里得算法是一個很好的解決同餘問題的算法,非常實用。
歐幾里得算法
簡介
歐幾里得算法,又稱輾轉相除法。
主要用途
求最大公因數gcd。
公式
gcd(a,b)=gcd(b,a%b)
公式證明
a可以表示成a=kb+a%b(k爲自然數)。
假設g是a,b的一個公約數,則有g∣a,g∣b。
∵a%b=a−kb,
∴g∣(a%b),∴g是b,a%b的公約數。
綜上所述,a,b和b,a%b的公約數是一樣的,其gcd也必然相等。
代碼實現
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)不斷輾轉相除。
根據歐幾里得算法,最後剩下的兩個數一定爲(gcd(a,b),0),
顯然,此時x=1,y=0是原式的一組解。
現在,我們需要考慮,若已知(b,a%b)的解,如何推出(a,b)的解。
設x0,y0爲(b,a%b)的一組解,則x0⋅b+y0(a%b)=gcd(b,a%b)。
將這個式子轉化一下,可以得到x0⋅b+y0(a−⌊ba⌋∗b)=gcd(a,b)。
去括號,得x0⋅b+y0⋅a−(y0⋅⌊ba⌋)⋅b=gcd(a,b)。
合併同類項,得y0⋅a+(x0−y0⋅⌊ba⌋)⋅b=gcd(a,b)。
∴x=y0,y=x0−y0⋅⌊ba⌋是原式的一組解。
遞歸即可。
代碼實現
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;
}
擴歐的典型應用:求乘法逆元
Link
乘法逆元 詳見博客 淺談乘法逆元的三種解法