文章目录
- 1 最大公约数
- 1.1 概念
- 1.2 求解
- 1.3 实现代码
- 2 最大公倍数
1 最大公约数
1.1 概念
最大公约数:正整数a和b的所有公约数中最大的那个公约数。
如:4和6的最大公约数是2,3和9的最大公约数是3。
1.2 求解
一般用gcd(a,b)来表示a和b的最大公约数,求解最大公约数常用欧几里得算法(辗转相除法)。
欧几里得算法基于下面这个定理:
gcd(a,b) = gcd(b, a % b);
证明过程:
设a = kb + r (a / b = k....r),其中k和r分别为得到的商和余数。
则有r = a - kb成立。
设d为a和b的一个公约数,
那么由r = a - kb,得d也是r的一个公约数。(a-kb得x倍的d,x根据实际情况确定)。
因此d是b和r的一个公约数。
由于r = a % b,得d为b和a%b的一个公约数。
因此d既是a和b的公约数,也是b和a%b的公约数。
由于d的任意性,得到a和b的公约数都是b和a%b的公约数。
设d是b和r的一个公约数,
那么由a = kb+r,得d也是a的一个约数,
因此d是a和b一个约数,
又因为r = a%b,得d为b和a%b的一个公约数。
由于d的任意性,b和a%b的公约数也是a和b的公约数。
即有gcd(a,b) = gcd(b,a%b)。
证毕。
通过上面的定理发现,如果a小于b,就交换a和b,如果a大于b,那么就可以将数据规模变小,并且减小的非常快。可以用递归来求解。由于0和任何一个整数a的最大公约数都是a(不是0),因此可以得到递归边界。
- 1 递归式:gcd(a,b) = gcd(a, a%b);
- 2 递归边界:gcd(a, 0) = a.
1.3 实现代码
int gcd(int a, int b){
if(b == 0) return a;
else return gcd(b, a%b);
}
简化版:
int gcd(int a, int b){
return !b ? a : gcd(b, a%b);
}
2 最大公倍数
正整数a、b的最大公约数即:集合a和集合b的交集,而最小公倍数为集合a和集合b的并集。要得到并集,由于ab会使得共因子部分多计算一次,因此需要除掉一次共因子,于是就得到了a和b的最小公倍数为ab/d。
由于ab在实际计算中有可能溢出,因此更恰当的写法是a/db。(d是a和b的最大公约数,a/d一定可以i整数)
2,算法实现
int gcd(int a, int b){
return !b ? a : gcd(b, a%b);
}
int lcm(int a, int b){
return a/gcd(a,b)*b;
}