最大公约数

最大公约数是个很常用的概念,例如 9 和 6 的最大公约数是 3 ,记作 gcd(9, 6) = 3 ,最小公倍数则为两数的乘积再除以它们的最大公约数,6×9 / gcd(6, 9) = 18 。

我们知道,含有两个未知数的二元一次方程可以表示成平面直角坐标系内的一条直线,f(x, y) = ax + by + c,当拥有两条相交直线我们通过代入消元可以得到唯一解,而只有一条直线时,则有无数个 (x, y) 坐标满足等式。

针对这样一个方程 ax + by = m ,贝祖定理告诉我们,当该方程有整数解时,当且仅当 m 是 a 和 b 的最大公约数的倍数,可以表示成 ax + by = gcd(a, b) * k (K∈Z) ,例如 9x + 6y = 12 有整数解,因为 12 = gcd(9, 6) * 4。特别地,方程 ax + by = 1 有整数解当且仅当 a 与 b 互质,即 gcd(a, b) = 1。这个定理在 RSA 加密算法中需要用到。

我们首先看两个数的最大公约数的求法,常用的方法是辗转相减法(又称更相减损术)和辗转相除法(又称欧几里得算法)。

以C语言代码的形式展示两种算法。

复制代码
 1 #include <stdio.h>
 2 
 3 int main() {
 4     int a, b, r;
 5     scanf("%d%d", &a, &b);
 6     
 7     // 辗转相减法 
 8 //    while(a != b) {
 9 //        a>b ? a-=b : b-=a;
10 //    }
11     
12     // 辗转相除法
13     r = 1;
14     while(r) {
15         r = a % b;
16         a = b;
17         b = r;
18     }
19     
20     printf("%d", a);
21     return 0;
22 }
复制代码

辗转相减法简单且容易记,每次以大数减小数,当两数减到相等时即为最大公约数。但效率不及辗转相除法,例如求 2000000000 与 1 的最大公约数,辗转相减法需要让 2000000000 不断自减一,直到等于 1 ,得到最大公约数 1 ,总共循环 2000000000-1 轮;辗转相除法则只需要一轮就可完成计算。

下面给出求若干正整数的最大公约数的C语言代码。

复制代码
 1 #include <stdio.h>
 2 
 3 #define MAX_LENGTH 3000
 4 
 5 int GCD(int *num, int n);
 6 
 7 /*
 8 8
 9 26 39 13 65 52 104 78 91
10 */
11 int main() {
12     int i, j, n, num[MAX_LENGTH], gcd;
13     
14     // 1. 数据输入 
15     scanf("%d", &n);
16     for(i=0; i<n; i++) {
17         scanf("%d", &num[i]);
18     }
19     
20     // 2. 获取该批数据的最大公约数 
21     gcd = GCD(num, n);
22     printf("%d", gcd);
23     
24     return 0;
25 }
26 
27 int GCD(int *num, int n) {
28     int i, j, r, gcd=num[0];
29     
30     for(i=1; i<n; i++) {
31         // 辗转相减法 
32 //        while(gcd != num[i]) {
33 //            gcd>num[i] ? gcd-=num[i] : num[i]-=gcd;
34 //        }
35         
36         // 辗转相除法
37         r = 1;
38         while(r) {
39             r = gcd % num[i];
40             gcd = num[i];
41             num[i] = r;
42         }
43     }
44     return gcd;
45 }
复制代码

 

posted @   HanselHuang  阅读(1878)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示