歐幾里得算法
歐幾里得算法就是大家以前學過的輾轉相除法,可以用來計算兩個數字的最大公約數(\(gcd\)):
\(gcd(a,b)=gcd(b,a\%b)\)
證明
對於 \(a,b\ (a\le b)\) 不妨設 \(a=kb+r\)
若 \(r=0\) 則說明 \(b|a\) ,所以 \(gcd(a,b)=b\)
若 \(r\ne0\) 則對於任意 \(t|a\) 且 \(t|b\) ,都有 \(t|kb\) ,又因為 \(a-kb=r\) ,所以也有 \(t|r\) ,同理,對於任意 \(t|r\) 且 \(t|b\) ,都有 \(t|kb\) ,又因為 \(r+kb=a\) ,所以也有 \(a|r\) ,所以 \(a,b\) 的所有公因數也就是 \(b,r\) 的所有公因數
c++ code
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
裴蜀定理(貝祖定理)
若 \(a,b\in\mathbb{Z}\) ,那么對於任意的 \(x,y\in\mathbb{Z}\) 都有 \(ax+by=k*gcd(a,b)\) ,其中 \(k\in\mathbb{Z}\) ,同時一定存在一組 \(x,y\in\mathbb{Z}\) 使得 \(ax+by=gcd(a,b)\) 成立
換言之,當且僅當 \(gcd(a,b)|m\) 時關於 \(x,y\) 的方程 \(ax+by=m\) 有整數解,我們稱這個等式為裴蜀等式,其有解時必然有無窮多個解,每一組解 \(x,y\) 被稱為裴蜀數,可以使用拓展歐幾里得算法來求解裴蜀數
證明
與下方擴展歐幾里得算法的推導方法類似,此處就不再贅述,請接着往下看
擴展歐幾里得算法
擴展歐幾里得算法就是利用歐幾里得算法原理推導出的求解裴蜀等式的解的算法
推導
對於 \(ax+by=gcd(a,b)\)
當 \(b=0\) 時,顯然 \(x=1,y=0\) 滿足等式
當 \(b>0\) 時,不妨設有 \(ax_1+by_1=gcd(a,b)\) 和 \(bx_2+(a\%b)y_2=gcd(b,a\%b)\)
根據歐幾里得算法的原理 \(gcd(a,b)=gcd(b,a\%b)\) ,可以得出
可以將 \(a\%b\) 展開為 \(a-b\lfloor\frac{a}{b}\rfloor\) ,原式就可以變形為
整理得
根據多項式恆等定理可以得出
這樣就知道了求解 \(x_1,y_1\) 的方法:通過遞歸,在 \(x_2,y_2\) 的基礎上算出 \(x_1,y_1\) ,當遞歸到 當 \(b=0\) 時,顯然 \(gcd(a,b)=a\),所以有 \(x=1,y=0\) ,遞歸結束
c++ code
int exgcd(int a,int b,int &x1,int &y1)
{
if(!b)//遞歸邊界
{
x1=1,y1=0;
return a;
}
int x2,y2;
int r=exgcd(b,a%b,x2,y2);//遞歸
x1=y2,y1=x2-(a/b)*y2;//使用結論
return r;
}
補充
我們上面的方法只算出了 \(ax+by=gcd(a,b)\) 的一組特解,對於更一般的方程 \(ax+by=c\) ,它有解當且僅當 \(gcd(a,b)|c\) ,我們把算出的特解都乘以 \(\frac{c}{gcd(a,b)}\) 就是 \(ax+by=c\) 的一組特解
那么怎么將這一組特解推廣到通解呢?
對於方程 \(ax+by=gcd(a,b)\) ,考慮把方程中的 \(x\) 加上一個數 \(k_1\),把 \(y\) 減去一個數 \(k_2\),只要保證原方程仍成立那么 \(x+k_1,y-k_2\) 就是一組新的解
把方程寫出
拆開括號並整理
可以看出滿足 \(ak_1=bk_2\) 時原方程仍成立,發現 \(ak_1,bk_2\) 都一定是 \(a,b\) 的公倍數,所以有
因此尋找一組新的解只要將 \(x\) 加上 \(\frac{b}{gcd(a,b)}\) ,將 \(y\) 減去 \(\frac{a}{gcd(a,b)}\) 就可以了
綜上,方程 \(ax+by=c\) 的通解可以表示為:
在實際應用時,為了得到最小正整數解,可以讓 \(x=\left(\left(\frac{c}{gcd(a,b)}x_0\right)\%\frac{b}{gcd(a,b)}+\frac{b}{gcd(a,b)}\right)\%\frac{b}{gcd(a,b)}\) ,對於 \(y\) 同理
應用
求乘法逆元
若 \(ax\equiv 1\pmod p\) 其中 \(gcd(a,p)=1\),那么我們就稱 \(x\) 為 \(a\) 在模 \(p\) 意義下的乘法逆元
求 \(ax\equiv 1\pmod p\) 的解就相當於求 \(ax+py=1\) 的解,使用擴歐即可,最后的結果模 \(p\) 就可以算出 \(a\) 在模 \(p\) 意義下的乘法逆元
該文為本人原創,轉載請注明出處