淺談擴展歐幾里得定理(附裴蜀定理)


                                關於擴展歐幾里得定理

  眾所周知,擴展歐幾里得定理是用來求形如ax+by=c(a,b,c皆為整數)這樣的方程的一組解[注,僅是一組解]的定理

  它的原理比較復雜,本人學了挺久才懂了一點,這里就不談了,擴歐的核心是它的思想,它的思想可以用來解決許多題

 該方程有解的條件 :

   要使ax+by=c(a,b,c皆為整數) 有解,我們設k=gcd(a,b),可以將原方程寫成\frac{a}{k}kx+\frac{b}{k}ky=c的形式

 即 k(\frac{a}{k}x+\frac{b}{k}y)=c

 

    \because   a,b,c均為整數

 \therefore (\frac{a}{k}x+\frac{b}{k}y)一定是整數即k(\frac{a}{k}x+\frac{b}{k}y)一定是k的倍數

    \therefore   k|c 即 gcd(a,b)|c          //  k|c數學里為  c%k=0

    由此可見,該方程有解的條件為c%gcd(a,b)=0

  求解方法 :

    由於是求解ax+by=c的一組解,在方程有解的條件下,我們可以考慮先求出ax+by=gcd(a,b)的一組解,

    為什么這樣考慮呢,這樣子變化有什么好處呢?當我們將原方程轉變為這樣的方程之后,實際上我們求出的x與y並不是

    原方程的解,我們可以理解為轉變后的方程的解為x'與y',實際上該ax+by=gcd(a,b)方程是將原方程除以

    c/gcd(a,b)后所得到的,所以原方程的解為\left\{\begin{matrix} x=x'(c/gcd(a,b))& & \\ y=y'(c/gcd(a,b))& & \end{matrix}\right.那么我們先求出ax+by=gcd(a,b)

    原方程的解便只需乘以c/gcd(a,b)就能得到了

    另外說明,c=gcd(a,b)是原方程有解的最小情況,利用這個性質,裴蜀定理也就不難寫出來了

    那么該如何求解ax+by=gcd(a,b)呢?

    眾所周知(又是這個詞,詞窮)   gcd的寫法return b==0?a:gcd(b,a%b);(為了節約篇幅強行壓縮)關鍵的一步就是

    gcd(a,b)==gcd(b,a%b)了,這個的成立性就不證明了,我們求解ax+by=gcd(a,b)是需要利用到gcd的這個特性的

    我們可以得到這樣一個方程\left\{\begin{matrix} & ax+by=gcd(a,b) & \\ & gcd(a,b)=gcd(b,a mod b) & \end{matrix}\right.(這里的%顯示不出來就用mod代替了),然后我們將gcd(b,a%b)中的b和a代入原方程

    那么可以得到gcd(b,a%b) = bx+(a%b)y,注意,此時的x與y也不是原方程的解,也可以理解為x',y'這樣子我們就可以得到

    ax+by=gcd(a,b)=gcd(b,a mod b)=bx'+(amodb)y'(這里是將gcd(a,b)的a,b反代入原方程),又因為電腦中的取模運算a%b是等價於a-a/b*b的

    所以我們又可以將最后一個方程變成bx'+(a-a/b*b)y',然后與第一個方程放在一起便有

    \dpi{150} ax+by=bx'+(a-a/b*b)y',然后拆項移項,變成ax+by=ay'+b(x'-a/by'),最后便能得出這樣的轉移方程

    \left\{\begin{matrix} x=y' & \\ y=x'-a/by' & \end{matrix}\right.,有了這樣的轉移方程,那么我們可以遞歸地寫出代碼了,遞歸結束條件就是b==0時,此時的方程

    ax+by=gcd(a,b),b==0,所以就是ax=a,那么x=1,y=0

   

//已知a,b 求解 ax+by=1 void ex_gcd (int a,int b,int &x,int &y) { if (b==0){x=1,y=0;return;} ex_gcd(b,a%b,x,y); int tmp=x; x=y,y=tmp-a/b*y; } /* * 若求解 ax+by=c * △條件(是否有解) : 滿足gcd(a,b)|c [c%gcd(a,b)==0] * 可以先求 ax+by=gcd(a,b) * 再將求得的x與y分別乘以c/gcd(a,b) */

    那么擴展歐幾里得便講完了,下面說一下上文提到的裴蜀定理

    原題鏈接

  裴蜀定理

  題目描述

    給出n個數(A1...An)現求一組整數序列(X1...Xn)使得S=A1X1+...AnXn>0,且S的值最小

  輸入輸出格式

    輸入格式:

    第一行給出數字N,代表有N個數 下面一行給出N個數

     輸出格式:

    S的最小值

    我們可以將A1X1+A2X2+...+AnXn看成許多個ax+by,那么我們要求的便是c的最小值,上文說過,c的最小值就是gcd(a,b),所以我們只需求出所有的gcd便可

    附上代碼

   

#include <cstdio> #include <cmath> using namespace std; int ans,n,t; int gcd (int a,int b) { return !b?a:gcd(b,a%b); } int main () { scanf("%d",&n); scanf("%d",&ans);//ans初始賦值為第一個數 while (--n){ scanf("%d",&t); t=abs(t); ans=abs(gcd(ans,t)); } printf("%d",ans); return 0; }

    注,如若有誤或者哪里講得不清楚,請聯系本人更改或者在下方留言,謝謝啦~\(≧▽≦)/~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM