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