辗转相除法

很多人都在用这种方法求最大公约数,但是知道为什么这样能求最大公约数的人就不多了。其实这是一个数论的定理:

y = ax + b => gcd(x, y) = gcd(b, x) (a, b, x, y ∈ Z)

只要证明了这个式子成立,只需要证明x、y的公约数和b、x的公约数相同即可,因为如果他们的约数都相同了,那么其中一定有一个是最大的。

首先介绍一些简单的数学知识:

y = ax(a, x, y ∈ Z),就说x能整除y,记作x|y

x|y, x|z => x|ax + bz(这个定理很简单就不做证明了)

算法的证明如下

设d|x, d|y

d|x, d|y => d|y-ax 即 d|b

所以有d|x, d|y => d|x, d|b

即x、y的约数都是b、x的约数

 

假定x,y ∈ Z,x >= y, 令r[0] = x , r[1] = y 用辗转相除法有:

1
2
3
4
5
6
7
8
9
10
11
12
13
r[0] = r[1] * q[1] + r[2]    0<=r[2]<r[1]
      
r[1] = r[2] * q[2] + r[3]    0<=r[3]<r[2]
      
            .
      
            .
      
            .
      
r[n-2] = r[n-1] * q[n-1] + r[n]    0<=r[n]<r[n-2]
      
r[n-1] = r[n]q[n]

 

在序列x=r[0]>r[1]>r[2]...>=0中最多有a项,最终余数为0

由y = ax + b => gcd(x, y) = gcd(b, x) (a, b, x, y ∈ Z)

gcd(x, y) = gcd(r[0], r[1]) = gcd(r[1], r[2])=...=r[n]

即:gcd(x, y )为辗转相除法中组后一个非0的余数

 

证明

简单的想法

设两数为a、b(a>b),求a和b最大公约数(a,b)的步骤如下:用b除a,得a÷b=q......r1(0≤r1)。若r1=0,则(a,b)=b;若r1≠0,则再用r1除b,得b÷r1=q......r2 (0≤r2).若r2=0,则(a,b)=r1,若r2≠0,则继续用r2除r1,……如此下去,直到能整除为止。其最后一个非零除数即为(a,b)。

原理及其详细证明

设两数为a、b(b<a),用gcd(a,b)表示a,b的最大公约数,r=a mod b 为a除以b以后的余数,k为a除以b的商,即a÷b=k.......r。辗转相除法即是要证明gcd(a,b)=gcd(b,r)。
第一步:令c=gcd(a,b),则设a=mc,b=nc
第二步:根据前提可知r =a-kb=mc-knc=(m-kn)c
第三步:根据第二步结果可知c也是r的因数
第四步:可以断定m-kn与n互素【否则,可设m-kn=xd,n=yd,(d>1),则m=kn+xd=kyd+xd=(ky+x)d,则a=mc=(ky+x)dc,b=nc=ycd,故a与b最大公约数成为cd,而非c,与前面结论矛盾】
从而可知gcd(b,r)=c,继而gcd(a,b)=gcd(b,r)。
证毕。
附上一个简单的C++程序的实现:
View Code
 1 #include<iostream>
 2 
 3 using namespace std;
 4 
 5 int main()
 6 
 7 {
 8     int a,b;
 9     cout<<"请输入两个正整数:"<<endl;
10     cin>>a;
11     cin>>b;     //输入两个要求公约数的整数
12 
13     int i,j;
14     int temp;
15 
16     if(a>b)    {i=a;j=b;}   //通过if语句来计算出除数和被除数
17     else       {i=b;j=a;}
18     
19     while(j!=0)  //辗转相除法来计算最大公约数
20     {
21         temp=i%j;
22         i=j;
23         j=temp;
24     }
25 
26 cout<<"两个数的最大公约数为:"<<i<<endl;
27 
28 return 0;

 

 

posted @ 2013-03-21 00:01  要往高处走  阅读(327)  评论(0编辑  收藏  举报