GCD
GCD,也就是最大公约数,即两个数拥有的相同的因数集中最大的一个。
求法
如果求任意两个数的GCD呢,相信小学的时候都学过辗转相除法,也就是欧几里得算法,当然还有以前学过的更相减损术,这里只讨论欧几里得算法(据说更相减损术是欧几里得算法的特殊情况)。
欧几里得算法
描述
欧几里得算法的内容是:
两个数的最大公约数是指能同时整除它们的最大正整数。
设两数为a,b(a≥b),求a和b最大公约数gcd(a,b)的步骤如下:
Ⅰ.用a除以b,a≥b,得a÷b=q…r1(0≤r1)。
Ⅱ.若r1=0,则gcd(a,b)=b;
Ⅲ.若r1=0,则再用b÷r1=q…r1(0≤r1)。
如此往复,直到余数为0,那么gcd(a,b)为除数。
证明
证明欧几里得算法,也就是证明:
Ⅰ.gcd(a,b)==gcd(b,amodb).
Ⅱ.所求为最优.
Ⅰ
首先设c为a,b的公因数,则设a=m×c,b=n×c。
设a=k×b+r,则得到r=a−k×b=m×c−k×n×c=(m−k×n)×c。
则c也为b和r的公因数。
再者,设b和r的公因数为v,则设
b=i×v
r=j×v
于是有a=k×b+r=k×i×v+j×v=(k×i+j)×v。
则a和b的公约数也为v.
综上我们可以使用这个递推。
Ⅱ
下面我们来推一下:
amodb=r
bmodr=r1
rmodr1=r2
……
rn−3modrn−2=rn−1
rn−2modrn−1=rn
由于a≥b≥0那么r1….rn是递减的,最终将变为0.
则当rn−1=0,rn==0时,可以得到rn−1∣rn−2(’|’为整除符号,a|b代表b能被a整除),则rn−2和rn−1的公约数只有rn−1和rn−1的约数,其中最大的就是rn−1。
代码实现
接下来给出代码实现
1 2 3
| int gcd(int x, int y){ return y?gcd(y, x%y):x; }
|
LCM
聊完GCD,再来聊聊LCM,也就是最小公倍数,即两个数公共的倍数集合中最小的元素。
求法
对于两个数a,b,有公式:
a×b=lcm(a,b)×gcd(a,b)。
证明
设x=gcd(a,b);
则n=a/x,m=b/x。显然a和m是互素的,所以lcm(n,m)=n×m,又因为lcm(a,b)=lcm(n×x,m×x)=x×n×m。
所以lcm(a,b)=gcd(a,b)×a/gcd(a,b)×b/gcd(a,b),即lcm(a,b)×gcd(a,b)=a×b
代码实现
1 2 3
| int lcm(int a, int b){ return a/gcd(a, b)*b; }
|
参考链接
Ⅰ.欧几里得算法证明
Ⅱ.境外之主