前言:求解最大公约数从高中一直到现在,始终是数学与程序设计的经典。现在,让我们看看GCD的四种解法
定义⋙
约数/因数(Divisor): 整数b除以整数a(b≠0) 除得的商正好是整数而没有余数,我们就说b能被a整除,或a能整除b。即:定义正整数a、b,有 b mod a=0,则称a为b的约数
倍数(multiple):一个整数能够被另一个整数整除,那么这个整数就是另一整数的倍数。即:定义正整数a,b,有b mod a=0,则称b为a的倍数
最大公约数【Greatest Common Divisor(GCD)】:也称最大公因数,最大公因子,指两个或多个整数共有约数中最大的一个。
a,b的最大公约数记为(a,b);
a,b,c的最大公约数记为(a,b,c)
最小公倍数【Least Common Multiple】:指两个或多个整数公有倍数中除零外最小的一个
a,b的最大公约数记为[a,b];
a,b,c的最大公约数记为[a,b,c]
问题描述⋙
给你两个正整数a、b,求a、b的最大公约数和最小公倍数,设已知a≧b
💥补充:[a,b]=a × b ÷ (a,b)
所以,我们只要求出a,b的最大公约数,最大公倍数便可直接求出
✨✈✈✈✈✈✈✈✈✈✈✈✈✈✈🛫🛫🛫🛫🛫🛫🛫🛫飞行分割线
1:朴素枚举法⋙
要求a、b的最大公约数,我们可以从大到小枚举a的约数,然后再判断它是不是b的约数,不断枚举,直到找到满足条件的最大公约数
[1]朴素枚举C/C++代码实现如下🌀
int gcd(int a,int b){
int mi=min(a,b);
int mx=max(a,b);
for(int i=mi;i>=2;i--){
//最好从两数中的较小者
if(mi%i==0&&mx%i==0) //开始枚举,以减少不必要的计算
return i;
}
return 1;
}
[2]朴素枚举法:流程图😈:
注:如果题目没给a、b的大小关系,加条补充
这个算法只经历一次循环,时间复杂度为O(n),貌似还可以,但有人给了我们更优的算法!他们是————
✔🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑解题分割线
2:欧几里得辗转相除法——《几何原本》⋙
[1]辗转相除法公式:gcd(a,b) = gcd(b,a mod b)
实现补充:非零数n与0的最大公约数永远为n
证明如下——
记a为两数中的更大数,b为较小数
1.首先,当b≠0时,记a=kb+r (a,b,k,r均为正整数,且r=a mod b)
2.假设d是a,b的一个公约数,记作d|a,d|b,即a和b都可以被d整除。
而r = a - kb,两边同时除以d,r/d=a/d-kb/d,由等式右边可知m=r/d为整数,因此d|r
3.因此d也是b,a mod b的公约数。
4.因(a,b)和(b,a mod b)的公约数相等,则其最大公约数也相等,得证gcd(a,b) = gcd(b,a mod b)
示例:
假如需要求 2022 和 507两个正整数的最大公约数,用欧几里得算法,是这样进行的:
2022/507=3 余501
507/501=1 余6
501/6=83 余3
6/<