1. 程式人生 > >(擴充套件)歐幾里德演算法

(擴充套件)歐幾里德演算法

新博文地址:  [狀態轉移思想解讀:歐幾里德演算法及擴充套件](http://blog.csdn.net/sunliymonkey/article/details/46755983)

歐幾里德是用來求最大公約數的,可以把它看成是狀態轉移,

對任意兩個數a,b(a>b),d=gcd(a,b),如果b不為零,那麼gcd(a,b)=gcd(b,a%b)

        證明: 令 r=a%b,即存在k,使得 a=b*k+r,那麼r=a-b*k;顯然r>=0,  r%d=((a%d)-(b*k)%d)%d,因為a%d=b%d=0,所以r%d=0;

因此求gcd(a,b)可以轉移到求gcd(b,a%b),那麼這就是個遞迴過程了,那什麼時候遞迴結束呢,想一下,a,b不能為零,則可以把當b為零,作為遞迴的結束(當然還可以以其它結束條件),這就是求最大公約數的方法可以以其它結束條件),這就是求最大公約數的方法

int gcd(int a,int b)
{
    if(b==0)return a;
 
    else return gcd(b,a%b);
 }

是不是很簡單呀.

理解了上面,那麼擴充套件歐幾里得就能很容易理解了,對任意a,b(a>b),我們列出這樣一個式子: a*x+b*y=gcd(a,b);

不要覺得擴充套件歐幾里得很牛逼,它就是一個算x,y的一個方法,只是在上面gcd中多了處理x,y的步驟

我們這樣來想:

已知當前的一個狀態:a1  b1  x1  y1,    a1*x1+b1*y1=gcd(a1,b1),注意這裡的a1,b1是求gcd(a,b)中的一個狀態,

假設 (a1,b1)是由(a0,b0)轉移過去的

那麼:   a1=b0 ;     b1=a0%b0=a0-k*b0 (k=int(a0/b0));gcd(a0,b0)=gcd(a1,b1);

代入a1*x1+b1*y1=gcd(a1,b1),變化成:b0*x1+(a0-k*b0)*y1=gcd(a1,b1)=gcd(a0,b0);

a0*y1+b0*(x1-k*y1)=gcd(a0,b0);

這樣可以得到: x0=y1;  y0=x1-k*y1;(理解這個過程了麼,由當前狀態可以算出上一狀態的x,y,即當前狀態可以由它的下一個狀態的x,y得到)

code:

int exGcd(int a,int b,int &x,int &y)
{
	if(b==0)
	{
		x=1;
		y=0;
		return a;// 此時a是最開始(a,b)的最大公約數,那麼  gcd(a,b)*1+ 0*0=gcd(a,b),肯定對的,在這裡,我認為,y可以為任何值都對
	}
	
	int d=exGcd(b,a%b,y,x);
	y-=a/b*x;
	return d;//返回最大公約數
}

應用:

擴充套件歐幾里得演算法的應用基本全都是基於:a*x+b*y=d 這個式子來發散的