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

                                關於擴展歐幾里得定理

  衆所周知,擴展歐幾里得定理是用來求形如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的形式

    \because   a,b,b均爲整數

    \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/b*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/by;
}
/*
 * 若求解  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;
}

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

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