欧几里得算法(辗转相除)及其扩展证明
2017-09-23 12:55
351 查看
首先欧几里得是谁???
学数学的人一定不陌生,一位为数学界做出重大贡献的人;(以下摘自百度百科)
欧几里得(希腊文:Ευκλειδης ,公元前330年—公元前275年),古希腊数学家。他活跃于托勒密一世(公元前364年-公元前283年)时期的亚历山大里亚,被称为“几何之父”,他最著名的著作《几何原本》是欧洲数学的基础,提出五大公设,欧几里得几何,被广泛的认为是历史上最成功的教科书。欧几里得也写了一些关于透视、圆锥曲线、球面几何学及数论的作品。(有兴趣的人可以自行百度)
那么欧几里得算法又是什么呢?
这个名字大家可能会有点陌生,但是辗转相除法肯定听说过,没错,欧几里得算法就是辗转相除法的大名,而辗转相除法则像一个外号;
欧几里得算法可以这样描述:有正整数a,b(a>b);a=n*b+r(n, r均为正整数);则a, b的最大公约数等于b, r的最大公约数;
公式表示为gcd(a,b)= gcd(b,a%b);(PS:gcd是greater common divisor(最大公约数)的缩写);
证明:
方法一:
假设 d为a,b的公约数,则d|a, d|b(d|a表示a能被d整除); 令a=x*d, b=y*d;则r=a-n*b=x*d-n*y*d=(x-n*y)*d; 所以r|d;所以d为b,a%b的公约数;
假设d为b,r的公约数;因为a=n*b+r;同理可得d|a;所以d为a,d的公约数;
综上所述:a,b的公约数= b,a%b的公约数;
那么同理gcd(a, b)=gcd(b, a%b);
方法二:
若gcd(a, b)=gcd(b, r)成立(r=a%b), 令c=gcd(a,b);a=m*c,b=n*c, 且n,m互质;
因为r=a%b,r=a-kb=m*c-kn*c=(m-k*n)*c;
假设n和(m-k*n)不互质,则n=x*d,(m-k*n)=y*d(d>1),m=y*d+k*x*d=(y+k*x)*d;a=m*c=(y+k*x)*d*c, b=n*c=x*d*c;所以a,b的最大公约数,与前提矛盾,所以n,(m-k*n)互质;
所以gcd(a,b)=gcd(b,a%b);
证明结束;
那么,该算法可以解决什么问题呢?很显然是求两个数的最大公约数了;
好,你一定迫不及待要看代码实现了,take it easy,NOW show U:
现在了解一下扩展欧几里得算法:
对于非负整数a,b必然存在整数对x,y使得a*x+b*y=gcd(a,b);(PS: x,y∈Z);
证明:
令a*x1+b*y1=gcd(a, b) (1) ; b*x2+a%d*y2=gcd(b, a%b) (2);
在计算机中a%d=a-(a/b)*b;所以(2)式可化简为 a*y2+b*(x2-(a/b)*y2)=gcd(b,a%b);
因为gcd(a, b)==gcd(b, a%d) , 所以a*x1+b*y1==a*y2+b*(x2-(a/b)*y2), 所以x1==y2, y1==(x2-(a/b)*y2);
由此我们可以看出x1,y1与x2,y2有关;但是x2,y2又怎么求呢????
我们可以取一个极值;当b=0时 gcd(a, b)=a;a*x+b*y=gcd(a, b)=a; 此时x,y有唯一解x=1,y=0(PS:其实唯一解这一说法不严谨,应该是x有唯一解:x=1;y可以是任意整数,此处为了简单化令y=0;当然无论y取何值都是可以的,不过此时y的取值决定了之后的x,y的解,毕竟a*x+b*y=gcd(a,b)的解不唯一);
有了极值之后,也就是有了递归的终点,那么就可以递归求出a*x+b*y=gcd(a,b)中x,y的一个解;
OK,SHOW U THE CODE:
#include <iostream>
using namespace std;
//函数返回值r表示a,b的最大公约数;
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 main(){
int a, b;
cin >> a >> b;
if(a<b){
a=a+b;
b=a-b;
a=a-b;
}
int x, y;
int r=exgcd(a, b, x, y);
cout << r << ' ' << x << ' ' << y;
return 0;
}
学数学的人一定不陌生,一位为数学界做出重大贡献的人;(以下摘自百度百科)
欧几里得(希腊文:Ευκλειδης ,公元前330年—公元前275年),古希腊数学家。他活跃于托勒密一世(公元前364年-公元前283年)时期的亚历山大里亚,被称为“几何之父”,他最著名的著作《几何原本》是欧洲数学的基础,提出五大公设,欧几里得几何,被广泛的认为是历史上最成功的教科书。欧几里得也写了一些关于透视、圆锥曲线、球面几何学及数论的作品。(有兴趣的人可以自行百度)
那么欧几里得算法又是什么呢?
这个名字大家可能会有点陌生,但是辗转相除法肯定听说过,没错,欧几里得算法就是辗转相除法的大名,而辗转相除法则像一个外号;
欧几里得算法可以这样描述:有正整数a,b(a>b);a=n*b+r(n, r均为正整数);则a, b的最大公约数等于b, r的最大公约数;
公式表示为gcd(a,b)= gcd(b,a%b);(PS:gcd是greater common divisor(最大公约数)的缩写);
证明:
方法一:
假设 d为a,b的公约数,则d|a, d|b(d|a表示a能被d整除); 令a=x*d, b=y*d;则r=a-n*b=x*d-n*y*d=(x-n*y)*d; 所以r|d;所以d为b,a%b的公约数;
假设d为b,r的公约数;因为a=n*b+r;同理可得d|a;所以d为a,d的公约数;
综上所述:a,b的公约数= b,a%b的公约数;
那么同理gcd(a, b)=gcd(b, a%b);
方法二:
若gcd(a, b)=gcd(b, r)成立(r=a%b), 令c=gcd(a,b);a=m*c,b=n*c, 且n,m互质;
因为r=a%b,r=a-kb=m*c-kn*c=(m-k*n)*c;
假设n和(m-k*n)不互质,则n=x*d,(m-k*n)=y*d(d>1),m=y*d+k*x*d=(y+k*x)*d;a=m*c=(y+k*x)*d*c, b=n*c=x*d*c;所以a,b的最大公约数,与前提矛盾,所以n,(m-k*n)互质;
所以gcd(a,b)=gcd(b,a%b);
证明结束;
那么,该算法可以解决什么问题呢?很显然是求两个数的最大公约数了;
好,你一定迫不及待要看代码实现了,take it easy,NOW show U:
#include <iostream> using namespace std; //递归实现: int gcd_1(int a, int b){ return a%b==0? b : gcd_1(b, a%b); } //迭代实现: int gcd_2(int a, int b){ while(b){ int c=b; b=a%b; a=c; } return a; } int main(){ int a, b; cin >> a >> b; if(a<b){ a=a+b; b=a-b; a=a-b; } int gcd1, gcd2; gcd1=gcd_1(a, b); gcd2=gcd_2(a, b); cout << "gcd1: " << gcd1 << endl; cout << "gcd2: " << gcd2 << endl; return 0; }
现在了解一下扩展欧几里得算法:
对于非负整数a,b必然存在整数对x,y使得a*x+b*y=gcd(a,b);(PS: x,y∈Z);
证明:
令a*x1+b*y1=gcd(a, b) (1) ; b*x2+a%d*y2=gcd(b, a%b) (2);
在计算机中a%d=a-(a/b)*b;所以(2)式可化简为 a*y2+b*(x2-(a/b)*y2)=gcd(b,a%b);
因为gcd(a, b)==gcd(b, a%d) , 所以a*x1+b*y1==a*y2+b*(x2-(a/b)*y2), 所以x1==y2, y1==(x2-(a/b)*y2);
由此我们可以看出x1,y1与x2,y2有关;但是x2,y2又怎么求呢????
我们可以取一个极值;当b=0时 gcd(a, b)=a;a*x+b*y=gcd(a, b)=a; 此时x,y有唯一解x=1,y=0(PS:其实唯一解这一说法不严谨,应该是x有唯一解:x=1;y可以是任意整数,此处为了简单化令y=0;当然无论y取何值都是可以的,不过此时y的取值决定了之后的x,y的解,毕竟a*x+b*y=gcd(a,b)的解不唯一);
有了极值之后,也就是有了递归的终点,那么就可以递归求出a*x+b*y=gcd(a,b)中x,y的一个解;
OK,SHOW U THE CODE:
#include <iostream>
using namespace std;
//函数返回值r表示a,b的最大公约数;
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 main(){
int a, b;
cin >> a >> b;
if(a<b){
a=a+b;
b=a-b;
a=a-b;
}
int x, y;
int r=exgcd(a, b, x, y);
cout << r << ' ' << x << ' ' << y;
return 0;
}
相关文章推荐
- 欧几里得算法(辗转相除)&扩展欧几里得
- 扩展欧几里得算法的非递归实现的证明
- 扩展欧几里得算法详解
- 欧几里得算法与其扩展 Romantic
- 扩展欧几里得算法
- 扩展欧几里得算法
- 欧几里得算法,扩展欧几里得算法及裴蜀定理证明
- 符号扩展(sign extension)的证明
- poj-1061-青蛙约会-扩展的欧几里得算法的模板题
- 扩展欧几里得证明详证
- 欧几里得算法:从证明等式gcd(m, n) = gcd(n, m mod n)对每一对正整数m, n都成立说开去
- 欧几里得算法与其扩展 Romantic
- 扩展欧几里得算法(POJ 1061)
- 扩展欧几里得算法
- vijos1009:扩展欧几里得算法
- 扩展欧几里得算法
- 扩展欧几里得算法
- 证明:欧几里得算法
- 欧几里得算法与其扩展
- 扩展欧几里得算法