歐幾里德算法
歐幾里德算法又稱輾轉相除法,用於計算兩個整數a,b的最大公約數。gcd函數就是用來求(a,b)的最大公約數的。
gcd函數的基本性質:
性質一:gcd(a,b)=gcd(b,a)=gcd(-a,b)=gcd(|a|,|b|)
證明略。
性質二:gcd(a,b)=gcd(b,a mod b)
證明:a可以表示成a = kb + r,則r = a mod b
假設d是a,b的一個公約數,則有 d|a, d|b,而r = a - kb,因此d|r ,d是(b,a mod b)的公約數
假設d 是(b,a mod b)的公約數,則 d|b , d|r ,又a = kb +r ,因此d也是(a,b)的公約數
因此(a,b)和(b,a mod b)的公約數是一樣的,其最大公約數也必然相等,得證。
利用性質二可得
//求GCD的循環方法
int Gcd(int a,int b)
{
for(int c=a%b;c;a=b,b=c,c=a%b);
return b;
}
//求GCD的遞歸方法
int Gcd(int a,int b)
{
return b?MGcd(b,a%b):a;
}
//時間複雜度O(lgn)
擴展歐幾里德算法
定理一:對於不完全爲 0 的非負整數 a,b,gcd(a,b)表示 a,b 的最大公約數,必然存在整 數對 x,y ,
使得gcd(a,b)=ax+by。
解:設a、b不全爲0,令a>b,
當b=0時,gcd(a,b)=a,解的情況爲x=1,y=0
當ab!=0,令
a*x1+b*y1 = gcd(a,b)
b*x2+(a%b)*y2 = gcd(b,a-a/b*b)
又gcd(a,b) = gcd(b,a-a/b*b)
故有a*x1+b*y1 = b*x2+(a%b)*y2
a*x1+b*y1 = b*x2+(a-a/b*b)*y2
= b*x2+a*y2-a/b*by2
= a*y2+b*(x2-a/b*y2)
即有,x1=y2, y1=x2-a/b*y2
由上推導可知,x1與y1的值可由x2、y2推知,拓展歐幾里得算法就是不斷地的將b放小,直至b等於0,最後反推求回x和y。
//算法,解方程ax+by=gcd(a,b),其中d=gcd(a,b)
void MEuclid(int a,int b,int &d,int &x,int &y)
{
if(b==0){d=a;x=1;y=0;return;}
MEuclid(b,a%b,d,y,x);
y-=x*(a/b);
}
遞歸求值:當b=0時,x=1,y=0 (ax+by = GCD(a,b));由x1=y2, y1=x2-a/b*y2倒推,最後求值。
解不定方程ax+by=c
定理二:對於不定整數方程ax+by=c ,若 c mod gcd(a,b)=0,則該方程存在整數解,否則不存在整數解。
故當c mod gcd(a,b)=0,先用擴展歐幾里得算法求出ax+by=gcd(a,b)的一組解x1,y1。
則x2=x1*c/gcd(a,b),y2=y1*c/gcd(a,b)爲ax+by=c的一組解。
x=x2+b/gcd(a,b)*t,y=y2-a/gcd(a,b)*t,(t爲整數),即爲ax+by=c的所有解。
轉載請註明出處,謝謝合作 http://blog.sina.com.cn/u/1885661061