歐幾里得算法及擴展

輾轉相除法

求整數a,b的最大公約數gcd(a,b):

定理:gcd(a,b)=gcd(b,a%b)

證明:設a除以b得到的商和餘數分別爲k和r,則a=kb+r,r=a%b,設d爲a,b公約數,則d一定整除r=a-kb,所以d是(b,a%b)的公約數。(a,b)和(b,a %b)公約數相同,最大公約數也一定相等。

根據該定理不斷操作下去最終得到gcd(a,b)=gcd(c,0)=c。複雜度在O(log max(a,b))以內 。

遞歸:

int gcd(int a,int b)
{
    return b?gcd(b,a%b):a;
}

非遞歸:

int gcd(int a,int b)
{
	int r;
	while(b)
	{
		r=a%b;
		a=b;
		b=r;
	}
	return a;
} 

擴展歐幾里得算法

二元一次不定方程ax+by=c,求整數解(x,y)使該等式成立。其中a、b、c均爲整數

a,b最大公約數爲gcd(a,b),c若不爲gcd(a,b)倍數,則方程無整數解,因爲左式一定爲gcd(a,b)倍數。

c爲gcd(a,b)的倍數時,等式有解。通過計算使ax1+by1=gcd(a,b)成立的x1、y1,然後由x=(c/gcd(a,b))*x1,y=(c/gcd(a,b))*y1,得到x,y。

利用擴展的歐幾里得算法遞歸求a*x+b*y=gcd(a,b)的一組整數解(設a>b)

b=0時,a*x=gcd(a,b)=a,得到x=1,y取0;

b≠0,設方程 ax1+by1=gcd(a,b);  bx2+(a%b)y2=gcd(b,a%b);

方程二代入a%b=a-(a/b)*b得 :bx2+(a%b)y2=bx2+(a-(a/b)*b)y2=ay2+b(x2-(a/b)y2)

由歐幾里得原理gcd(a,b)=gcd(b,a%b)得 ax1+by1= ay2+b(x2-(a/b)y2)

則可根據x2,y2求出x1=y2,y1=x2-(a/b)y2。

擴展歐幾里得算法遞歸代碼:

int extend_euclid(int a,int b,int& x,int& y)
{//返回最大公約數 
	if(b==0)
	{
		x=1;y=0;
		return a;
	}
	else
	{
		int d=extend_euclid(b,a%b,y,x);
		y-=(a/b)*x;
		return d;
	} 
} 

求解ax+by=c

bool linear_equation(int a,int b,int c,int &x,int &y)
{
	int d=extend_euclid(a,b,x,y);
	if(c%d)//c不是最大公約數的倍數,無解 
		return false;
	int k=c/d;
	x*=k;y*=k;
	return true;
}

 

 

 

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