gcd 和 lcm 相关结论和性质

138 阅读2分钟

前言: 在本文章中要介绍一下gcd和lcm的性质 ,以及一些使用的技巧 , 其中也包括一些定理的证明。

gcd 部分

gcd 是什么 ?

gcd 的全称是最大公约数(Greatest common divisor)

gcd 是对两个及以上的数的运算数才存在 , 但是一般的我们是求两个数的最大公约数即 gcd(a , b)

举个例子 , 4 , 12 的gcd 是多少呢 ? 答案是 4

4 的因数 1 2 2 4
12 的因数 1 2 3 4 6 12

其中我们发现 4 是他们最大的公共的因数

是不是非常的清楚明了!

gcd(a , b) 的形式化表达

对于任意的一个自然数 a , b 由唯一分解定理都可以表示成这样的形式

a=p1k1  p2k2  p3k3  p4k4....... pnknb=p1l1  p2l2  p3l3  p4l4....... pnln a = p_1^{k_1} \ · \ p_2^{k_2} \ · \ p_3^{k_3} \ · \ p_4^{k_4}....... \ p_n^{k_n}\\\\ b = p_1^{l_1} \ · \ p_2^{l_2} \ · \ p_3^{l_3} \ · \ p_4^{l_4}....... \ p_n^{l_n}

那么我们的gcd(a , b) 可以形式化表示成这样

gcd (a , b)=p1min(k1,l1)  p2min(k2,l2)  p3min(k3,l3)......pnmin(kn,ln) gcd \ (a \ , \ b) = p_1^{min(k_1 , l_1)} \ · \ p_2^{min(k_2 , l_2)} \ · \ p_3^{min(k_3 , l_3)} ...... p_n^{min(k_n , l_n)}

那我们该怎么求gcd(a , b) , 当然使用 辗转相除法!也叫欧几里得算法

欧几里得算法

欧几里得算法计算公式:

gcd(a , b)=gcd(b ,amod b),其中 mod 是取模gcd(a \ , \ b) = gcd(b \ , a \mod\ b) , 其中 \ mod \ 是取模

对应的代码也非常的好写

int gcd(int  a , int b){

     return b ? gcd(b , a % b) : a;
}

注: 本人目前还不清楚gcd(a , b) 证明,以后应该会知道的。


接下来介绍一下gcd 的一些性质

gcd(a,b)gcd(a , b) 记成 (a,b)(a , b)

1 . (a,b)=(a,a+b)=(a+b,b)=(ab,b)=(b,ab)(a , b) = (a , a + b) = (a + b , b) = (a - b , b) = (b , a - b)

2 . 结合律 : (a ,b , c)=((a,b),c)=(a,(b,c))(a\ , b\ ,\ c) = ((a , b) , c) = (a , (b , c))

  • 推论 :
(a1,a2,a3.....,an)=(a1,(a2,......,an))=((a1,a2,......an1)an) (a_1 , a_2 , a_3 ..... , a_n) = (a_1 , (a_2 , ...... , a_n)) = (( a_1 , a_2 , ...... a_{n-1}) a_n)

对于这里的推论 , 其实我们可以发现 gcd(a1,a2,a3,......,an)gcd(a_1 , a_2 , a_3 , ...... , a_n) 可以通过先对其中两个数的求公约数, 然后对剩下的aia_i进行一一的即可

3 . 互质 : (a,b)=(dk1,dk2)(a , b) = (dk_1 , dk_2) , 其中d为最大公约数, (k1,k2)=1(k_1 , k_2) = 1 , 即 k1,k2k_1 , k_2 互质. 同时 k1,k2,k1+k2k_1 , k_2 , k_1 + k_2 三者互质

4 . 分配律 : (m a,m b)=m (a , b)(m\ a , m\ b) = m \ (a \ , \ b)

  • 推论: 设(a,b,c)=1(a , b , c) = 1, 其中a,b,ca , b , c 都是正整数 , 那么 (a,b)(b,c)=(ab,c)(a , b) * (b , c) = (ab , c).
(a , b)(b , c)=(ab , c) (a \ , \ b) * (b\ , \ c) = (ab \ , \ c)

证明:
(a , b)  (b , c)( a \ , \ b) \ * \ (b \ , \ c)
= (a(b,c),c(b,c))(a (b , c), c (b , c)) // 分配律
= (ab,ac,bc,cc)(ab , ac , bc , cc)
= (ab ,c (a,b,c))(ab \ , c\ (a , b , c)) // 结合律
= (ab , c)(ab \ , \ c) // 由题(a , b , c) = 1
证毕!

5 . 不知道名字的性质 :

gcd(a1,a2,a3,a4,.....,an)=gcd(a1,a1+a2,...,a1+a2+a3.....+an) gcd(a_1 , a_2 , a_3 , a_4 , ..... , a_n) = gcd(a_1 , a_1 + a_2 ,...,a_1 + a_2 + a_3 ..... + a_n)

证明 gcd(a1,a2,a3,a4,.....,an)=gcd(a1,a1+a2,...,a1+a2+a3.....+an)gcd(a_1 , a_2 , a_3 , a_4 , ..... , a_n) = gcd(a_1 , a_1 + a_2 ,...,a_1 + a_2 + a_3 ..... + a_n)

首先假设有 a , b 两数 , 很显然我们可以求出 gcd(a,b)=dgcd(a , b) = d

这里我们不妨设 a=dk1,b=dk2a = dk_1 , b = dk_2 , 同时将 gcd(a , b)记成 (a , b)

首先我们先来证明

(a,a+b)=(a,b) (a , a + b) = (a , b)

这里我们可以将 (a , a + b) 写成 (dk1,d(k1+k2))(dk_1 , d(k_1 + k_2)) 此时我们表示成 d(k1,(k1+k2))d(k_1 , (k_1 + k_2))

因为(k1,(k1+k2))=1(k_1 , (k_1 + k_2)) = 1 , 所以 d(k1,(k1+k2))=1d(k_1 , (k_1 + k_2)) = 1.

现在通过这个证明观察 , 我们发现其实对于n 元的也可以利用这种拆分方法

类似的也可以证明

(a1,a2,a3,.....,an)=(a1,a1+a2,a1+a2+a3.....,a1+a2+......+an)(a_1 , a_2 , a_3 , ..... , a_n) = (a_1 , a_1 + a_2 , a_1 + a_2 + a_3 ..... , a_1 + a_2 + ...... + a_n)

对于以上结论也有类似的结论: (a1,a2,a3,.....,an)=(a1,a1a2,a1a2a3.....,a1a2......an)(a_1 , a_2 , a_3 , ..... , a_n) =(a_1 , a_1 - a_2 , a_1 - a_2 - a_3 ..... , a_1 - a_2 - ...... - a_n)

同时有:
(a1,a2,a3,.....,an)=(a1,a2a1,a3a2.....,anan1)(a_1 , a_2 , a_3 , ..... , a_n) = (a_1 , a_2 - a_1 , a_3 - a_2 ..... , a_n - a{n-1})


第一种证明 :

我们可以利用结合率来一步步求即:

((a1,a1+a2),a1+a2+a3,a1+a2+a3+a4......,a1+a2+a3+...an) ((a_1 , a_1 + a_2) , a_1 + a_2 + a_3 , a_1 + a_2 + a_3 + a_4 ...... ,a_1 + a_2 + a_3 + ... a_n)

可以将 a1,a2.....an写成dki的形式其中d(a1,a2,.....,an)a_1 , a_2 ..... a_n 写成 dk_i 的形式 其中 d 为 (a_1 , a_2 , ..... , a_n)

即:

(d(k1,k1+k2),d(k1+k2+k3)......,d(k1,k2,k3....kn)) (d(k_1 , k_1 + k_2) , d(k_1 + k_2 + k_3) ...... , d(k_1 , k_2 , k_3 .... k_n))

利用上述的结合率 因为(k1,k1,k2)(k_1 , k_1 , k_2) 互质 所以 , 我们可以直接将 d(k1,k1+k2)d(k_1 , k_1 + k_2) 直接写成 d

对于后面的项:

(d1,d(k1+k2+k3)......,d(k1,k2,k3....kn))(d * 1, d(k_1 + k_2 + k_3) ...... , d(k_1 , k_2 , k_3 .... k_n))

因为 1 和任何数都互质 , 所以结果就是 d

另一种证明方式 :

我们来证 n = 3 时的情况:

即有 (a,b,c)=(a,a+b,a+b+c)(a , b , c) = (a , a + b , a + b + c)
我们通过结合律可以得到:
(a , (a + b , a + b + c))
再由 (a , b) = (a , b - a)
我们可以先得到 (a , (a + b , a + b + c - a - b))
---> (a, a+b,c)(a ,\ a + b , c)
------> ( (a , a + b) , c) 同理
-------> (a , b , c)

到此得证!

n = 4 , 5 , 6 ...... m 都可以类似证明!

6 . 单调性: 这个性质比较有意思!描述的东西就是区间 [L , R]gcd 一定会小于等于区间[L , R + d] 因为我们每次加入一个数, gcdgcd都可能被丢掉一个因数 , 所以gcd 是有区间单调性的。

形式化表达:

gcd([L,R])>=gcd([L,R+d]),其中0<=d gcd([L , R]) >= gcd([L , R + d]) , 其中 0 <= d

这时候如果询问区间gcd的话 , 就可以利用二分。

lcm

lcm 全称是 Least common multiple ,即最小公倍数


lcm(a,b)lcm(a , b) 形式化表达:

对于任意的一个自然数 a , b 由唯一分解定理都可以表示成这样的形式

a=p1k1  p2k2  p3k3  p4k4....... pnknb=p1l1  p2l2  p3l3  p4l4....... pnln a = p_1^{k_1} \ · \ p_2^{k_2} \ · \ p_3^{k_3} \ · \ p_4^{k_4}....... \ p_n^{k_n}\\\\ b = p_1^{l_1} \ · \ p_2^{l_2} \ · \ p_3^{l_3} \ · \ p_4^{l_4}....... \ p_n^{l_n}

那么我们的 lcm(a , b) 可以形式化表示成这样

lcm (a , b)=p1max(k1,l1)  p2max(k2,l2)  p3max(k3,l3)......pnmax(kn,ln) lcm \ (a \ , \ b) = p_1^{max(k_1 , l_1)} \ · \ p_2^{max(k_2 , l_2)} \ · \ p_3^{max(k_3 , l_3)} ...... p_n^{max(k_n , l_n)}

举个例子:

a = 3
b = 8
lcm(a , b) = 24        // 公倍数

那么我们如何去求lcm(a , b) ? 其实我们发现gcdlcm 一些性质 , 从lcm,gcdlcm , gcd 的形式化表达中我们可以观察到最大最小幂数的取法 , 无论如何都是来自两个数中的。所以我们可以发现

lcm(a,b)  gcd(a,b)=a  blcm(a , b) \ · \ gcd(a , b) = a \ · \ b

证明:

p1max(k1,l1)+min(k1,l1)  p2max(k2,l2)+min(k2,l2)  p3max(k3,l3)+min(k3,l3)......pnmax(kn,ln)+min(kn,ln)=p1k1+l1  p2k2+l2  p3k3+l3  p4k4+l4....... pnkn+lnp_1^{{max(k_1 , l_1)} + {min(k_1 , l_1)}} \ · \ p_2^{{max(k_2 , l_2)} + {min(k_2 , l_2)}} \ · \ p_3^{{max(k_3 , l_3)} + {min(k_3 , l_3)}} ...... p_n^{{max(k_n , l_n)} + {min(k_n , l_n)}} \\ = p_1^{k_1 + l_1} \ · \ p_2^{k_2 + l_2} \ · \ p_3^{k_3 + l_3} \ · \ p_4^{k_4 + l_4}....... \ p_n^{k_n + l_n}

因为 max(ki,li)+min(ki,li)=ki+li (1<=i<=n)max(k_i , l_i) + min(k_i , l_i) = k_i + l_i \ (1 <= i <= n)
所以上述等式一定成立!

特别地 ,当gcd(a , b) = 1 , 即 a , b 互质

lcm(a,b)=a  b lcm(a , b) = a \ · \ b

快速求出lcm

因为gcd(a , b) 容易求出 , 所以可以通过等式直接求出lcm

lcm(a,b)=abgcd(a,b) lcm(a , b) = \frac{a · b}{gcd(a , b)}

但是很多时候aba · b非常容易溢出 , 例如 a = 1e8 , b = 1e12 如果直接求 aba · b 那么直接会爆long long

那么我们可以利用乘法和除法的交换律 那么我们可以将公式交换成这样:

lcm(a,b)=agcd(a,b)  blcm(a , b) = \frac{a}{gcd(a , b)} \ · \ b

代码如下:

int lcm(int a ,  int b){

	return a / gcd(a , b) * b;
}