您的位置:首页 > 其它

最小公倍数和最大公约数之小结

2009-04-20 19:30 148 查看
今天看了HDOJ上的1019题,题目的核心在于求两个数的最小公倍数(lowest common multiple),我想既然看到了这个题目,就把相关求两个数最小公倍数和最大公约数(greatest common divisor)之类的东西总结一下吧,于是就有了这篇文章,文章中参考了部分网络上的资源,尤其是求最大公约数的欧几里德算法,感谢。

首先说明下求最大公约数的欧几里德算法,也叫辗转相除法,如下:

欧几里德算法(辗转相除法),用于计算两个整数a,b的最大公约数。

其计算原理依赖于下面的定理:

定理:gcd(a,b) = gcd(b,a mod 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)的公约数是一样的,其最大公约数也必然相等,得证!

(注 x|y:y可以被x整除,即 y mod x == 0 )

因此,求a和b的最大公约数就相当于求 b和a%b的最大公约数,如此循环下去,直到a mod b为零为止,因为如果a mod b为零的话,就说明gcd(a,b) = b了,结束。可根据上述算法描述写出程序如下:(分为递归和非递归)

//递归算法
int gcd_recursive(int a,int b)
//非递归算法
int gcd_non_recursive(int a,int b)
//求两个数的最小公倍数
//方法:两个数的乘积除以两个数的最大公约数
//即:lcm = a*b/gcd(a,b)
int lcm(int a,int b)
//如果是求一系列数的最大公约数,那么就可以采用递归方式从最后一个数开始
//逐个计算一个数组的最后一个数a[n-1]和前n-1个数的最大公约数就可以了
//以下的求一系列数的最小公倍数道理相同
int gcd_n(int *a,int n)

int lcm_n(int *a,int n)
{
if(n == 1)
return *a;
else
return lcm(a[n-1],lcm_n(a,n-1));
}
结.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: