最大公约数与最小公倍数
最大公约数(GCD)
欧几里得算法(辗转相除法)
辗转相除法的算法描述:
给定两个自然数a和b,若a mod b = 0(a是b的倍数),gcd(a, b) = b,否则,gcd(a, b) = gcd(b, a mod b)
可以用递归函数实现。
代码如下:
long long GCD(long long a, long long b)
{
return b == 0 ? a : GCD(b, a % b);
}
详细证明如下:
设
r
=
a
 
m
o
d
 
b
r=a\bmod b
r=amodb,现在证明,当
r
̸
=
0
r\not=0
r̸=0时,
g
c
d
(
a
,
b
)
=
g
c
d
(
b
,
r
)
gcd(a,b) = gcd(b,r)
gcd(a,b)=gcd(b,r):
令
c
=
g
c
d
(
a
,
b
)
c=gcd(a,b)
c=gcd(a,b),则
∃
m
,
n
∈
N
\exist m,n\in\mathbb{N}
∃m,n∈N,使得
a
=
m
∗
c
a=m*c
a=m∗c,
b
=
n
∗
c
b=n*c
b=n∗c
设
a
=
k
∗
b
+
r
a=k*b+r
a=k∗b+r,则
a
−
k
∗
b
=
r
a-k*b=r
a−k∗b=r,即
(
m
−
k
∗
n
)
∗
c
=
r
(m-k*n)*c=r
(m−k∗n)∗c=r
在这里用反证法证明:
m
−
k
∗
n
m-k*n
m−k∗n与
n
n
n互质
若
m
−
k
∗
n
m-k*n
m−k∗n与
n
n
n不互质,则
∃
d
∈
N
且
d
>
1
\exist d\in\mathbb{N}且d>1
∃d∈N且d>1,使得
m
−
k
∗
n
=
x
∗
d
m-k*n=x*d
m−k∗n=x∗d,
n
=
y
∗
d
n=y*d
n=y∗d
则
a
=
m
∗
c
=
(
x
+
k
∗
y
)
∗
c
∗
d
a=m*c=(x+k*y)*c*d
a=m∗c=(x+k∗y)∗c∗d,
b
=
n
∗
c
=
y
∗
c
∗
d
b=n*c=y*c*d
b=n∗c=y∗c∗d
g
c
d
(
a
,
b
)
=
c
∗
d
>
c
gcd(a,b)=c*d>c
gcd(a,b)=c∗d>c,与
g
c
d
(
a
,
b
)
=
c
gcd(a,b)=c
gcd(a,b)=c矛盾
所以,
m
−
k
∗
n
m-k*n
m−k∗n与
n
n
n互质
又因为
r
=
(
m
−
k
∗
n
)
∗
c
r=(m-k*n)*c
r=(m−k∗n)∗c,
b
=
n
∗
c
b=n*c
b=n∗c
所以,
g
c
d
(
b
,
r
)
=
c
gcd(b,r)=c
gcd(b,r)=c
因此
g
c
d
(
a
,
b
)
=
g
c
d
(
b
,
r
)
=
c
gcd(a,b)=gcd(b,r)=c
gcd(a,b)=gcd(b,r)=c
更相减损术
更相减损术是《九章算术》中记载的一种可以用来约分的方法,但这种方法也可以用来求最大公约数。原文是:可半者半之,不可半者,副置分母、子之数,以少减多,更相减损,求其等也。以等数约之。
译文:
可以折半的话,就折半。如果不可以折半的话,那么就比较分母和分子的大小,用大数减去小数,互相减来减去,一直到减数与差相等为止,用这个相等的数字来约分。
这本来是一种求约分的方法,下面介绍如何将它转化为求最大公约数的方法:
给定两个数a,b
第一步:如果给定的a,b都是偶数,则不断地将a,b除以二化简,直至a,b中至少有一个不是偶数。
第二步:将a,b中较大的数减去较小的数,并将较小的数与两数之差作为新的a与b。不妨设a > b,则a - b与b就是新的a与b,不断重复这个操作,直至a与b相等。
第一步中约掉的若干个2的相乘再乘以第二步中最后得到的等数就是所求的最大公约数。
long long GCD(long long a, long long b)
{
long long c = 1LL;
while (a % 2 == 0 && b % 2 == 0)//第一步
{
a >>= 1;
b >>= 1;
c <<= 1;
}
while (a != b)//第二步
if (a > b) a -= b;
else b -= a;
return a * c;
}
最小公倍数(LCM)
对任意的两个自然数a与b,
a * b = gcd(a, b) * lcm(a, b)
因此,lcm(a, b) = a * b / gcd(a, b)
long long LCM(long long a, long long b)
{
return a / GCD(a, b) * b;//为了防止数据溢出,先除后乘
}