[数论]Gcd/ExGcd欧几里得学习笔记
\(Q\):什么是\(GCD\)?
- \(GCD\)
\(GCD\),即最大公約數(shù)(\(Greatest\ Common\ Divisor\))
對(duì)于兩個(gè)自然數(shù)\(a,b\),定義\(GCD(a,b)\)為\(a,b\)所有公共約數(shù)中最大的一個(gè),即\(GCD(a,b)=\max\{x\in N^*,x|a\)且\(x|b\}\)
然后是關(guān)于\(GCD\)的算法即其擴(kuò)展
\(Part1\) 歐幾里得算法
\(Q\):這個(gè)算法有什么用?
此算法可以在\(log\)級(jí)別里求出兩個(gè)數(shù)\(a,b\)的\(GCD\)
- 歐幾里得算法
對(duì)于\(a,b\),設(shè)它們的\(GCD\)為\(d\)。
則有:\(d|a\)且\(d|b\)
設(shè)\(a=k*{}b+r(k=\left\lfloor\frac{a}{b}\right\rfloor,r=a\mod b)\)
則:\(d|(a-k*{}b)\),即\(d|r\)
所以\(GCD(a,b)=GCD(b,r)=GCD(b,a\mod b)\)
最后遞歸求解,可在\(O(log_2a)\)內(nèi)得解。
時(shí)間復(fù)雜度 \(O(log_2a)\)
空間復(fù)雜度 \(O(log_2a)\)(遞歸棧)
實(shí)際復(fù)雜度一般到不了此上界。
代碼:
//求GCD(a,b) #include <cstdio>int GCD(int a,int b) {return b?GCD(b,a%b):a;//當(dāng)b為0時(shí),GCD(a,0)=a,充當(dāng)遞歸邊界。 }int main() {int a,b;scanf("%d%d",&a,&b);printf("%d\n",GCD(a,b));return 0; }\(Part2\) 擴(kuò)展歐幾里得
\(Q\):這個(gè)奇怪的算法又是什么啊?
首先,先來(lái)看一個(gè)不定方程:
\[ax+by=c\]
擴(kuò)展歐幾里得就是用來(lái)求此方程的不定解\((x,y)\)的。
準(zhǔn)備知識(shí):
- \(Bezout\)定理
對(duì)于兩個(gè)整數(shù)\(a,b\)存在一對(duì)整數(shù)\(x,y\),滿足\(ax+by=GCD(a,b)\)
證明:
在調(diào)用歐幾里得算法時(shí),當(dāng)\(b=0\),顯然有\(x=1,y=0\)滿足定理。
當(dāng)\(b\not= 0\)時(shí),若已經(jīng)求得,\(x,y\),使得
\[bx+(a\mod b)y=GCD(b,a\mod b)\]
則
\[bx+(a-b\left\lfloor\frac{a}{b}\right\rfloor)y=GCD(b,a\mod b)\]
\[ay+b(x-\left\lfloor\frac{a}{b}\right\rfloor y)=GCD(b,a\mod b)\]
設(shè)\(x'=y,y'=x-\left\lfloor\frac{a}{b}\right\rfloor y\),則有
\[ax'+by'=GCD(b,a\mod b)=GCD(a,b)\]
利用數(shù)學(xué)歸納法,知道\(Bezout\)成立。
同時(shí),我們可以利用此定理求出一組\(ax+by=GCD(a,b)\)的解。
時(shí)間復(fù)雜度 \(O(log_2a)\)
空間復(fù)雜度 \(O(log_2a)\)
代碼:
//求x,y使得ax+by=GCD(a,b),同時(shí)得到GCD(a,b) #include <cstdio>int ExGCD(int a,int b,int &x,int &y) {if(!b){x=1,y=0;return a;}//遞歸邊界int GCD=ExGCD(b,a%b,x,y);int Tmp=x;x=y,y=Tmp-a/b*y;return GCD; }int main() {int a,b,GCD,x,y;scanf("%d%d",&a,&b);GCD=ExGCD(a,b,x,y);printf("%d %d %d\n",GCD,x,y);return 0; }接著回到正題:對(duì)于方程\(ax+by=c\),它有解僅當(dāng)\(GCD(a,b)|c\)。
證明?不會(huì),記住就行,畢竟顯然。
接著,求出方程\(ax+by=GCD(a,b)\)的一組解,則:
\[ax+by=GCD(a,b)\]
\[\frac{c}{GCD(a,b)}*{}(ax+by)=c\]
\[a*\frac{cx}{GCD(a,b)}+b*\frac{cy}{GCD(a,b)}=c\]
于是就有了一組解:\(x'=\frac{cx}{GCD(a,b)},y'=\frac{cy}{GCD(a,b)}\)(對(duì)\(x,y\)同時(shí)乘上\(\frac{c}{GCD(a,b)}\))
于是問(wèn)題得解。
時(shí)間復(fù)雜度 \(O(log_2a)\)
空間復(fù)雜度 \(O(log_2a)\)
代碼:
//求x,y使得ax+by=c,同時(shí)得到GCD(a,b) #include <cstdio>int ExGCD(int a,int b,int &x,int &y) {if(!b){x=1,y=0;return a;}//遞歸邊界int GCD=ExGCD(b,a%b,x,y);int Tmp=x;x=y;y=Tmp-a/b*y;return GCD; }int main() {int a,b,c,GCD,x,y;scanf("%d%d%d",&a,&b,&c);GCD=ExGCD(a,b,x,y);if(c%GCD)return puts("Orz I cannot find it!"),0;//無(wú)解int d=c/GCD;printf("%d %d %d\n",GCD,x*d,y*d);return 0; }關(guān)于通解以及\(x\)最小正整數(shù)解。
設(shè)\(d=GCD(a,b)\),
\(x_0,y_0\)為\(ax+by=GCD(a,b)\)的一組特解,
\(x=x_0+km,y=y_0+kn(k\in \mathbb{Z})\)為方程的通解表示(k為任意整數(shù)),
則:
\[ax+by=ax_0+by_0\]
\[a(x_0+km)+b(y_0+kn)=ax_0+by_0\]
\[am+bn=0\]
顯然,當(dāng)\(m=-b,n=a\)時(shí)等式成立。
又因?yàn)橐?span id="ozvdkddzhkzd" class="math inline">\(m,n\)比例降到最小,所以同時(shí)除去\(GCD\)。
最后的通解表示為:
\[x=x_0-k\frac{b}ozvdkddzhkzd,y=y_0+k\frac{a}ozvdkddzhkzd(k\in \mathbb{Z})\]
同理,對(duì)于方程\(ax+by=c\)的通解為:
\[x=\frac{c}ozvdkddzhkzdx_0-k\frac{b}ozvdkddzhkzd,y=\frac{c}ozvdkddzhkzdy_0+k\frac{a}ozvdkddzhkzd(k\in \mathbb{Z})\]
所以求\(x\)的最小整數(shù)解只需要將\(x\mod \frac{b}ozvdkddzhkzd\)再推出\(y\)即可。
時(shí)間復(fù)雜度 \(O(log_2a)\)
空間復(fù)雜度 \(O(log_2a)\)
代碼:
//求ax+by=c的x最小正整數(shù)解。 #include <cstdio>int ExGCD(int a,int b,int &x,int &y) {if(!b){x=1,y=0;return a;}//遞歸邊界int GCD=ExGCD(b,a%b,x,y);int Tmp=x;x=y;y=Tmp-a/b*y;return GCD; }int main() {int a,b,c,d,x,y;scanf("%d%d%d",&a,&b,&c);d=ExGCD(a,b,x,y);if(c%d)return puts("Orz I cannot find it!"),0;//無(wú)解x*=c/d,y*=c/d;int f=b/d;x=(x%f+f)%f;y=(c-a*x)/b;printf("%d %d\n",x,y);//x最小正整數(shù)解。return 0; }所有性質(zhì)證明到此結(jié)束。
歐幾里得是個(gè)好東西,然而我不會(huì)用。
數(shù)論博大精深,不能就此止步,還要繼續(xù)探索。
祝自己\(++OI::RP\)
轉(zhuǎn)載于:https://www.cnblogs.com/LanrTabe/p/10370627.html
超強(qiáng)干貨來(lái)襲 云風(fēng)專訪:近40年碼齡,通宵達(dá)旦的技術(shù)人生總結(jié)
以上是生活随笔為你收集整理的[数论]Gcd/ExGcd欧几里得学习笔记的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。