求两个正整数的最大公约数
欧几里德算法简单分析
算法:
long gcd( long m, long n )
{
while( n!=0 )
{
long rem = n;
n = m % n;
m=rem;
}
return m;
}
分析:
设两个正整数m和n,m >=n != 0,其最大公约数为x。
m = ax; n=bx;
因为 任何一个非质素都是质素的乘积,所以x为m和n的公因子的乘积。
所以a >= b !=0且 a 与b 无公因子,且当其中一个为1时即得解。(一下讨论b!=1的情况)
接下来就是如何通过对m和n的计算来得到x,一种算法就是将n = bx 中的b因子或者m=ax中的a因子逐渐减小到1而保持x因子不变。
因为对于a和b的信息我们不能直接得出,而要实现上面的计算,一种方法就是用减法:
tem = m – n = ( a – b ) x;
y = a – b 与 b 无公因子,证明:假设y 与 b 存在公因子 z,则a = y + b = z(y/z+b/z),则a也含有因子z,这与a与b无公因子不符。所以y与b也公因子。所以:
tem与n的最大公约数也为x。于是问题转化为求tem与n的最大公约数,此时tem小于m,问题被逐渐减小。
更快的一种减小a 与 b 的方法:
a > b 且 a、b无公因子------>
a = yb + c;(y>=1,c>0)
m = ax = (yb +c )x=yn + cx;
同理,c与b无公因子,令tem = cx, 则tem与n最大公约数为x,且c<b;
这 c = a % b; tem = m % n ; 这中方法显然比上一种方法中a、b的减小速度快得多;
因为 b > c ,问题转化为求n 与tem 的最大公约数。
依次迭代计算 ,直到 tem = x 为止,即求出最大公约数x。
while( (bx) == 0 )
{
(cx) = (ax) % (bx) ;
(ax) = (bx);
(bx) = (cx);
}
其中 b == 0 必出现的论证:
c = a % b; 0 = < c < b < a; 如此迭代必出现c == 0;
该算法时间复杂度的估算:
c = a % b ; c < a/2; 在算法中即表现为n(余数)每两次循环至少减少为原来的一半,所以该算法时间复杂度估算为 2logn = O( logn ); 由于能力有限,更精确复杂的时间复杂度的计算还没有掌握。在最坏的情况下(如m和n是两个相邻的斐波那契数时)可以稍微改进成1.44logn。欧几里德算法在平均情况下的性能需要大量篇幅的高度复杂的数学分析,其迭代的平均次数约为(12ln2lnn)/pi2+1.47。