欧几里得算法扩展欧几里得算法
生活随笔
收集整理的這篇文章主要介紹了
欧几里得算法扩展欧几里得算法
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
歐幾里德算法又稱輾轉相除法,用于計算兩個整數a,b的最大公約數。
基本算法:設a=qb+r,其中a,b,q,r都是整數,則gcd(a,b)=gcd(b,r),即gcd(a,b)=gcd(b,a%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(a,b)=gcd(b,r),其中 gcd是取最大公約數的意思,r=a mod b
? ? 下面證 gcd(a,b)=gcd(b,r)
? ? 設 ?c是a,b的最大公約數,即c=gcd(a,b),則有 a=mc,b=nc,其中m,n為正整數,且m,n互為質數
? ? 由 r= a mod b可知,r= a- qb 其中,q是正整數,
? ? 則 r=a-qb=mc-qnc=(m-qn)c
? ? b=nc,r=(m-qn)c,且n,(m-qn)互質(假設n,m-qn不互質,則n=xd, m-qn=yd 其中x,y,d都是正整數,且d>1
? ? 則a=mc=(qx+y)dc, b=xdc,這時a,b 的最大公約數變成dc,與前提矛盾, 所以n ,m-qn一定互質)則gcd(b,r)=c=gcd(a,b)
? ? 得證。
算法的實現:
最簡單的方法就是應用遞歸算法,代碼如下:
int gcd(int a,int b)
{
? ? if(b==0)
? ? ? ? return a;
? ? return
? ? ? ? gcd(b,a%b);
}
代碼可優化如下:
?int gcd(int a,int b)
?{
? ? return b ? gcd(b,a%b) : a;
?}
迭代形式:
int Gcd(int a, int b)
{
? ? while(b != 0)
? ? {
? ? int r = b;
? ? b = a % b;
? ? a = r;
? ? }
? ? return a;
}
擴展歐幾里德算法
基本算法:對于不完全為 0 的非負整數 a,b,gcd(a,b)表示 a,b 的最大公約數,必然存在整數對 x,y ,使得 gcd(a,b)=ax+by。
證明:設 a>b。
1,顯然當 b=0,gcd(a,b)=a。此時 x=1,y=0;
2,ab!=0 時
?設 ax1+by1=gcd(a,b);
? bx2+(a mod b)y2=gcd(b,a mod b);
根據樸素的歐幾里德原理有 gcd(a,b)=gcd(b,a mod b);
則:ax1+by1=bx2+(a mod b)y2;
即:ax1+by1=bx2+(a-(a/b)*b)y2
? ? ? ? ? ? ? =ay2+bx2-(a/b)*by2;
根據恒等定理得:x1=y2; y1=x2-(a/b)*y2;
? ? ?這樣我們就得到了求解 x1,y1 的方法:x1,y1 的值基于 x2,y2.
?上面的思想是以遞歸定義的,因為 gcd 不斷的遞歸求解一定會有個時候 b=0,所以遞歸可以結束。
擴展歐幾里德的遞歸代碼:
int exgcd(int a,int b,int &x,int &y)
{
? ? if(b==0)
? ? {
? ? ? ? x=1;
? ? ? ? y=0;
? ? ? ? return a;
? ? }
? ? int r=exgcd(b,a%b,x,y);
? ? int t=x;
? ? x=y;
? ? y=t-a/b*y;
? ? return r;
}
?擴展歐幾里德非遞歸代碼(沒看):
int exgcd(int m,int n,int &x,int &y)
{
? ? int x1,y1,x0,y0;
? ? x0=1; y0=0;
? ? x1=0; y1=1;
? ? x=0; y=1;
? ? int r=m%n;
? ? int q=(m-r)/n;
? ? while(r)
? ? {
? ? ? ? x=x0-q*x1; y=y0-q*y1;
? ? ? ? x0=x1; y0=y1;
? ? ? ? x1=x; y1=y;
? ? ? ? m=n; n=r; r=m%n;
? ? ? ? q=(m-r)/n;
? ? }
? ? return n;
}
擴展歐幾里德算法的應用主要有以下三方面:
(1)求解不定方程;
(2)求解模線性方程(線性同余方程);
(3)求解模的逆元 ;
(1)使用擴展歐幾里德算法解決不定方程的辦法:
? 對于不定整數方程pa+qb=c,若 c mod Gcd(p, q)=0,則該方程存在整數解,否則不存在整數解。
? 上面已經列出找一個整數解的方法,在找到p*a+q*b =Gcd(p, q)的一組解p0,q0后,p*a+q*b = Gcd(p, q)的其他整數解滿足:
? p=p0+b/Gcd(p,q)*t
? q=q0-a/Gcd(p, q)*t(其中t為任意整數)
? 至于pa+qb=c的整數解,只需將p*a+q*b=Gcd(p, q)的每個解乘上 c/Gcd(p, q) 即可。
? 在找到p*a+q*b=Gcd(a, b)的一組解p0,q0后,應該是得到p*a+q*b=c的一組解p1=p0*(c/Gcd(a,b)),q1 = q0*(c/Gcd(a,b)),
? p*a+q*b=c的其他整數解滿足:
? p = p1 + b/Gcd(a, b) * t
? q = q1 - a/Gcd(a, b) * t(其中t為任意整數)
? p 、q就是p * a+q * b = c的所有整數解。
相關證明可參考:http://www.cnblogs.com/void/archive/2011/04/18/2020357.html
用擴展歐幾里得算法解不定方程ax+by=c;
(2)用擴展歐幾里德算法求解模線性方程的方法:
? ? 同余方程 ax≡b (mod n)對于未知數 x 有解,當且僅當 gcd(a,n) | b。且方程有解時,方程有 gcd(a,n) 個解。
? ? 求解方程 ax≡b (mod n) 相當于求解方程 ax+ ny= b, (x, y為整數)
? ? 設 d= gcd(a,n),假如整數 x 和 y,滿足 d= ax+ ny(用擴展歐幾里德得出)。如果 d| b,則方程
? ? a* x0+ n* y0= d, 方程兩邊乘以 b/ d,(因為 d|b,所以能夠整除),得到 a* x0* b/ d+ n* y0* b/ d= b。
? ? 所以 x= x0* b/ d,y= y0* b/ d 為 ax+ ny= b 的一個解,所以 x= x0* b/ d 為 ax= b (mod n ) 的解。
? ? ax≡b (mod n)的一個解為 x0= x* (b/ d ) mod n,且方程的 d 個解分別為 xi= (x0+ i* (n/ d ))mod n {i= 0... d-1}。
? ? 設ans=x*(b/d),s=n/d;
? ? 方程ax≡b (mod n)的最小整數解為:(ans%s+s)%s;((解%增長周期)+增長周期)%增長周期
? ? 相關證明:
? ? 證明方程有一解是: x0 = x'(b/d) mod n;
? ? 由 a*x0 = a*x'(b/d) (mod n)
? ? ? ? ?a*x0 = d (b/d) (mod n) ? (由于 ax' = d (mod n))
? ? ? ? ? ? ? ? ?= b (mod n)
? ? 證明方程有d個解: xi = x0 + i*(n/d) ?(mod n);
? ? 由 a*xi (mod n) = a * (x0 + i*(n/d)) (mod n)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?= (a*x0+a*i*(n/d)) (mod n)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?= a * x0 (mod n) ? ? ? ? ? ? (由于 d | a)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?= b
首先看一個簡單的例子:
5x=4(mod3)
解得x = 2,5,8,11,14......
由此可以發現一個規律,就是解的間隔是3.
那么這個解的間隔是怎么決定的呢?
如果可以設法找到第一個解,并且求出解之間的間隔,那么就可以求出模的線性方程的解集了.
我們設解之間的間隔為dx.
那么有
a*x = b(mod n);
a*(x+dx) = b(mod n);
兩式相減,得到:
a*dx(mod n)= 0;
也就是說a*dx就是a的倍數,同時也是n的倍數,即a*dx是a 和 n的公倍數.為了求出dx,我們應該求出a 和 n的最小公倍數,此時對應的dx是最小的.
設a 和 n的最大公約數為d,那么a 和 n 的最小公倍數為(a*n)/d.
即a*dx = a*n/d;
所以dx = n/d.
因此解之間的間隔就求出來了.
? ? 代碼如下:
bool linear_equation(int a,int b,int c,int &x,int &y)
{
? ? int d=exgcd(a,b,x,y);
? ? if(c%d)
? ? ? ? return false;
? ? int k=c/d;
? ? x*=k; y*=k; ? ?//求得的只是其中一組解
? ? return true;
}
(3)用歐幾里德算法求模的逆元:
? ? ? ?同余方程ax≡b (mod n),如果 gcd(a,n)== 1,則方程只有唯一解。
? ? ? 在這種情況下,如果 b== 1,同余方程就是 ax=1 (mod n ),gcd(a,n)= 1。
? ? ? 這時稱求出的 x 為 a 的對模 n 乘法的逆元。
? ? ? 對于同余方程 ax= 1(mod n ), gcd(a,n)= 1 的求解就是求解方程
? ? ? ax+ ny= 1,x, y 為整數。這個可用擴展歐幾里德算法求出,原同余方程的唯一解就是用擴展歐幾里德算法得出的 x 。
基本算法:設a=qb+r,其中a,b,q,r都是整數,則gcd(a,b)=gcd(b,r),即gcd(a,b)=gcd(b,a%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(a,b)=gcd(b,r),其中 gcd是取最大公約數的意思,r=a mod b
? ? 下面證 gcd(a,b)=gcd(b,r)
? ? 設 ?c是a,b的最大公約數,即c=gcd(a,b),則有 a=mc,b=nc,其中m,n為正整數,且m,n互為質數
? ? 由 r= a mod b可知,r= a- qb 其中,q是正整數,
? ? 則 r=a-qb=mc-qnc=(m-qn)c
? ? b=nc,r=(m-qn)c,且n,(m-qn)互質(假設n,m-qn不互質,則n=xd, m-qn=yd 其中x,y,d都是正整數,且d>1
? ? 則a=mc=(qx+y)dc, b=xdc,這時a,b 的最大公約數變成dc,與前提矛盾, 所以n ,m-qn一定互質)則gcd(b,r)=c=gcd(a,b)
? ? 得證。
算法的實現:
最簡單的方法就是應用遞歸算法,代碼如下:
int gcd(int a,int b)
{
? ? if(b==0)
? ? ? ? return a;
? ? return
? ? ? ? gcd(b,a%b);
}
代碼可優化如下:
?int gcd(int a,int b)
?{
? ? return b ? gcd(b,a%b) : a;
?}
迭代形式:
int Gcd(int a, int b)
{
? ? while(b != 0)
? ? {
? ? int r = b;
? ? b = a % b;
? ? a = r;
? ? }
? ? return a;
}
擴展歐幾里德算法
基本算法:對于不完全為 0 的非負整數 a,b,gcd(a,b)表示 a,b 的最大公約數,必然存在整數對 x,y ,使得 gcd(a,b)=ax+by。
證明:設 a>b。
1,顯然當 b=0,gcd(a,b)=a。此時 x=1,y=0;
2,ab!=0 時
?設 ax1+by1=gcd(a,b);
? bx2+(a mod b)y2=gcd(b,a mod b);
根據樸素的歐幾里德原理有 gcd(a,b)=gcd(b,a mod b);
則:ax1+by1=bx2+(a mod b)y2;
即:ax1+by1=bx2+(a-(a/b)*b)y2
? ? ? ? ? ? ? =ay2+bx2-(a/b)*by2;
根據恒等定理得:x1=y2; y1=x2-(a/b)*y2;
? ? ?這樣我們就得到了求解 x1,y1 的方法:x1,y1 的值基于 x2,y2.
?上面的思想是以遞歸定義的,因為 gcd 不斷的遞歸求解一定會有個時候 b=0,所以遞歸可以結束。
擴展歐幾里德的遞歸代碼:
int exgcd(int a,int b,int &x,int &y)
{
? ? if(b==0)
? ? {
? ? ? ? x=1;
? ? ? ? y=0;
? ? ? ? return a;
? ? }
? ? int r=exgcd(b,a%b,x,y);
? ? int t=x;
? ? x=y;
? ? y=t-a/b*y;
? ? return r;
}
?擴展歐幾里德非遞歸代碼(沒看):
int exgcd(int m,int n,int &x,int &y)
{
? ? int x1,y1,x0,y0;
? ? x0=1; y0=0;
? ? x1=0; y1=1;
? ? x=0; y=1;
? ? int r=m%n;
? ? int q=(m-r)/n;
? ? while(r)
? ? {
? ? ? ? x=x0-q*x1; y=y0-q*y1;
? ? ? ? x0=x1; y0=y1;
? ? ? ? x1=x; y1=y;
? ? ? ? m=n; n=r; r=m%n;
? ? ? ? q=(m-r)/n;
? ? }
? ? return n;
}
擴展歐幾里德算法的應用主要有以下三方面:
(1)求解不定方程;
(2)求解模線性方程(線性同余方程);
(3)求解模的逆元 ;
(1)使用擴展歐幾里德算法解決不定方程的辦法:
? 對于不定整數方程pa+qb=c,若 c mod Gcd(p, q)=0,則該方程存在整數解,否則不存在整數解。
? 上面已經列出找一個整數解的方法,在找到p*a+q*b =Gcd(p, q)的一組解p0,q0后,p*a+q*b = Gcd(p, q)的其他整數解滿足:
? p=p0+b/Gcd(p,q)*t
? q=q0-a/Gcd(p, q)*t(其中t為任意整數)
? 至于pa+qb=c的整數解,只需將p*a+q*b=Gcd(p, q)的每個解乘上 c/Gcd(p, q) 即可。
? 在找到p*a+q*b=Gcd(a, b)的一組解p0,q0后,應該是得到p*a+q*b=c的一組解p1=p0*(c/Gcd(a,b)),q1 = q0*(c/Gcd(a,b)),
? p*a+q*b=c的其他整數解滿足:
? p = p1 + b/Gcd(a, b) * t
? q = q1 - a/Gcd(a, b) * t(其中t為任意整數)
? p 、q就是p * a+q * b = c的所有整數解。
相關證明可參考:http://www.cnblogs.com/void/archive/2011/04/18/2020357.html
用擴展歐幾里得算法解不定方程ax+by=c;
(2)用擴展歐幾里德算法求解模線性方程的方法:
? ? 同余方程 ax≡b (mod n)對于未知數 x 有解,當且僅當 gcd(a,n) | b。且方程有解時,方程有 gcd(a,n) 個解。
? ? 求解方程 ax≡b (mod n) 相當于求解方程 ax+ ny= b, (x, y為整數)
? ? 設 d= gcd(a,n),假如整數 x 和 y,滿足 d= ax+ ny(用擴展歐幾里德得出)。如果 d| b,則方程
? ? a* x0+ n* y0= d, 方程兩邊乘以 b/ d,(因為 d|b,所以能夠整除),得到 a* x0* b/ d+ n* y0* b/ d= b。
? ? 所以 x= x0* b/ d,y= y0* b/ d 為 ax+ ny= b 的一個解,所以 x= x0* b/ d 為 ax= b (mod n ) 的解。
? ? ax≡b (mod n)的一個解為 x0= x* (b/ d ) mod n,且方程的 d 個解分別為 xi= (x0+ i* (n/ d ))mod n {i= 0... d-1}。
? ? 設ans=x*(b/d),s=n/d;
? ? 方程ax≡b (mod n)的最小整數解為:(ans%s+s)%s;((解%增長周期)+增長周期)%增長周期
? ? 相關證明:
? ? 證明方程有一解是: x0 = x'(b/d) mod n;
? ? 由 a*x0 = a*x'(b/d) (mod n)
? ? ? ? ?a*x0 = d (b/d) (mod n) ? (由于 ax' = d (mod n))
? ? ? ? ? ? ? ? ?= b (mod n)
? ? 證明方程有d個解: xi = x0 + i*(n/d) ?(mod n);
? ? 由 a*xi (mod n) = a * (x0 + i*(n/d)) (mod n)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?= (a*x0+a*i*(n/d)) (mod n)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?= a * x0 (mod n) ? ? ? ? ? ? (由于 d | a)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?= b
首先看一個簡單的例子:
5x=4(mod3)
解得x = 2,5,8,11,14......
由此可以發現一個規律,就是解的間隔是3.
那么這個解的間隔是怎么決定的呢?
如果可以設法找到第一個解,并且求出解之間的間隔,那么就可以求出模的線性方程的解集了.
我們設解之間的間隔為dx.
那么有
a*x = b(mod n);
a*(x+dx) = b(mod n);
兩式相減,得到:
a*dx(mod n)= 0;
也就是說a*dx就是a的倍數,同時也是n的倍數,即a*dx是a 和 n的公倍數.為了求出dx,我們應該求出a 和 n的最小公倍數,此時對應的dx是最小的.
設a 和 n的最大公約數為d,那么a 和 n 的最小公倍數為(a*n)/d.
即a*dx = a*n/d;
所以dx = n/d.
因此解之間的間隔就求出來了.
? ? 代碼如下:
bool linear_equation(int a,int b,int c,int &x,int &y)
{
? ? int d=exgcd(a,b,x,y);
? ? if(c%d)
? ? ? ? return false;
? ? int k=c/d;
? ? x*=k; y*=k; ? ?//求得的只是其中一組解
? ? return true;
}
(3)用歐幾里德算法求模的逆元:
? ? ? ?同余方程ax≡b (mod n),如果 gcd(a,n)== 1,則方程只有唯一解。
? ? ? 在這種情況下,如果 b== 1,同余方程就是 ax=1 (mod n ),gcd(a,n)= 1。
? ? ? 這時稱求出的 x 為 a 的對模 n 乘法的逆元。
? ? ? 對于同余方程 ax= 1(mod n ), gcd(a,n)= 1 的求解就是求解方程
? ? ? ax+ ny= 1,x, y 為整數。這個可用擴展歐幾里德算法求出,原同余方程的唯一解就是用擴展歐幾里德算法得出的 x 。
總結
以上是生活随笔為你收集整理的欧几里得算法扩展欧几里得算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第3周实践项目7 删除链表元素最大值
- 下一篇: 第4周实践项目1 建立单链表(非多组织结