最大公约数
约数:如果 a 可以整除 b,则 a 为 b 的约数, b a \frac{b}{a} ab 也是 b 的约数,约数也叫因数。
试除法求约数
我们可以用上一章讲到的判断质数的方法,这里只需要判断能否整除,非常简单
参考上一篇文章质数判断
代码如下:
for(int i = 1; i <= n/i; i++){
if(n % i == 0) cout<<i<<" "<<n/i<<endl;//i 与 n/i 都是因数
}
欧几里得算法(辗转相除法)
两个数的最大公约数简写为 gcd(a, b),即两个数的公共因数中最大的那个数。
那么如何求两个数的最大公约数呢 ?
这种算法的核心内容是 gcd(a, b) = gcd(b, a%b)
算法步骤
给定两非负整数 a, b (不得同时为0),重复以下操作:
- 用 a 除以 b , 得到余数 r
- 将 a 替换为 b , b 替换为 r
当某次余数 r = 0 时, 此时的 a 即为原两数的最大公约数
证明
GCD不变性
假设 d 为 a, b 的公约数,存在唯一的一个 商q 与 余数r
使
a
=
b
∗
q
+
r
a = b\ast q + r
a=b∗q+r
设
a
=
k
1
∗
d
a = k_1 \ast d
a=k1∗d
b
=
k
2
∗
d
b = k_2 \ast d
b=k2∗d
有
d
∗
k
1
=
(
d
∗
k
2
)
∗
q
+
r
d \ast k_1 = ( d \ast k_2 ) \ast q+ r
d∗k1=(d∗k2)∗q+r
整理后
r
=
d
∗
(
k
1
−
k
2
∗
q
)
r = d \ast ( k_1 - k_2 \ast q )
r=d∗(k1−k2∗q)
所以 d 必须能整除 a, b, 同时也能整除余数 r ;
反过来,若 d = gcd(b , r), 则 d 也能整除 a
因此,gcd(a, b) = gcd(b, r), 每一步替换后, GCD保持不变
严格递减性
由于每次计算的 r 满足 0 ≤ \leq ≤ r < b, 余数严格递减, 最终必然在有限步内达到 r = 0
终止条件
当余数 r = 0 时, gcd(a, 0) = a,此时 a 即为原两数的GCD
代码
int gcd(int a, int b){
if(b == 0) return a;
return gcd(b, a%b);
}
最小公倍数( lcm(A, B) )
公式
l c m ( A , B ) = ( A ∗ B ) / g c d ( A , B ) lcm(A, B) = (A \ast B ) / gcd(A, B) lcm(A,B)=(A∗B)/gcd(A,B)
证明
对于两个数 A, B,我们设 A = a ∗ k A = a \ast k A=a∗k, B = b ∗ k B = b \ast k B=b∗k (k 为 gcd(A, B) )
因为
A
∗
B
=
A
∗
B
A \ast B = A\ast B
A∗B=A∗B
带入, 得:
A
∗
(
b
∗
k
)
=
(
a
∗
k
)
∗
B
A \ast ( b \ast k ) = ( a \ast k ) \ast B
A∗(b∗k)=(a∗k)∗B
化简:
A
∗
b
=
a
∗
B
A \ast b = a \ast B
A∗b=a∗B
等式两边就是我们要找的 lcm(A, B)
易推得 l c m ( A , B ) = ( A ∗ B ) / g c d ( A , B ) lcm(A, B) = (A \ast B ) / gcd(A, B) lcm(A,B)=(A∗B)/gcd(A,B)
代码很简单, 这里就不放了
5843

被折叠的 条评论
为什么被折叠?



