跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

最大公约数 (GCD) 与最小公倍数 (LCM) 计算方法详解

最大公约数(GCD)与最小公倍数(LCM)的计算涉及多种经典算法,包括辗转相除法、更相减损法、分解质因数法、穷举法及递归实现。文章结合 C++ 代码示例解析欧几里得算法原理,并通过等差数列最短项数问题展示 GCD 在算法竞赛中的应用,帮助读者掌握数论基础算法。

指针猎手发布于 2026/2/6更新于 2026/5/2925 浏览
最大公约数 (GCD) 与最小公倍数 (LCM) 计算方法详解

一、什么是公约数

公约数,也称为公因数,是指两个或多个整数共有的因数。具体来说,如果一个整数能被两个或多个整数整除,那么这个整数就是这些整数的公约数。

例如,考虑整数 12 和 18:

  • 12 的因数有:1, 2, 3, 4, 6, 12
  • 18 的因数有:1, 2, 3, 6, 9, 18

12 和 18 的公约数是它们共有的因数,即:1, 2, 3, 6

补充:最小公倍数 (LCM)

**定理:**a、b 两个数的最小公倍数 (lcm) 乘以它们的最大公约数 (gcd) 等于 a 和 b 本身的乘积。

如:gcd(a,b) * lcm(a,b) = a*b

所以,只要学会 gcd,lcm 就能直接推导出来:

lcm(a,b) = a*b / gcd(a,b)

二、计算最大公约数的方法

学习数论的一系列算法时,往往直接看算法是看不懂的。这里我们先学习数学解法,再给出算法实现。

1. 辗转相除法(欧几里得算法)

数学原理

假设我们有两个正整数 a 和 b,其中 a > b。根据辗转相除法,最大公约数 gcd(a,b) 可以通过以下步骤求得:

  1. 第一步:计算 a % b,得到余数 r。
  2. 第二步:将 a 替换为 b,将 b 替换为 r。
  3. 第三步:重复上述步骤,直到 b=0 时,此时 a 即为最大公约数。

下方用 (18, 12) 举例。

文章配图

代码实现
#include <iostream>
using namespace std;

// 求公约数
int gcd(int a, int b){
    while(a % b != 0){
        int c = a % b;
        a = b;
        b = c;
    }
    return b;
}

int main(){
    int a, b;
    a = 18;
    b = 12;
    cout << gcd(a, b) << endl;
    return 0;
}

2. 更相减损版(辗转相减法)

数学原理

更相减损法是一种古老的算法,用于求两个正整数的最大公约数(GCD)。它最早出现在中国古代数学著作《九章算术》中。

更相减损法的基本原理是:对于任意两个正整数 a 和 b(假设 a ≥ b),如果 a 和 b 都是偶数,则可以用 2 约简;如果 a 和 b 不都是偶数,则用较大的数减去较小的数,然后继续对所得的差和较小的数进行同样的操作,直到两个数相等为止。这个相等的数就是它们的最大公约数。

文章配图

代码实现
#include <iostream>
using namespace std;

/**
 * 函数功能:计算两个整数的最大公约数(Greatest Common Divisor, GCD)
 * 参数:
 *   a: 第一个整数
 *   b: 第二个整数
 * 返回值:
 *   a 和 b 的最大公约数
 * 算法:采用更相减损术来计算最大公约数
 */
int func(int a, int b) {
    // 只要 a 与 b 的差值不为 0,就持续循环
    while (a - b != 0) {
        // 计算 a 减去 b 的差值,并将结果存储在临时变量 c 中
        int c = a - b;
        // 把 b 的值赋给 a
        a = b;
        // 把差值 c 的值赋给 b
        b = c;
    }
    // 当 a 与 b 的差值为 0 时,说明此时 a 和 b 相等,这个相等的值就是 a 和 b 的最大公约数
    return a;
}

int main() {
    int a, b;
    a = 18;
    b = 12;
    cout << func(a, b) << endl;
    return 0;
}

3. 其他方法

其他方法不像辗转相除法与更相减损法那么简便,在此简要介绍。

1. 分解质因数

文章配图

#include <stdio.h>

void fun(int *arr, int n) {
    int i = 2, j = 0;
    while (n > 1) {
        if (n % i == 0) {
            arr[j++] = i;
            n /= i;
        } else {
            i++;
        }
    }
}

int gcd(int a, int b) {
    // 因为要进行找这个数的共有的因数,所以这里用数组来接收
    int arr_a[100] = {0}; // 放 a 的所有因数
    int arr_b[100] = {0}; // 放 b 的所有因数
    
    // 进行放因数
    fun(arr_a, a);
    fun(arr_b, b);
    
    // 找出公共的因数,然后相乘
    int i = 0, j = 0, ret = 1;
    while (arr_a[i] != 0 && arr_b[j] != 0) {
        if (arr_a[i] == arr_b[j]) {
            ret *= arr_a[i];
            i++;
            j++;
        } else if (arr_a[i] > arr_b[j]) {
            j++;
        } else {
            i++;
        }
    }
    return ret;
}

int main() {
    int a = 0;
    int b = 0;
    scanf("%d %d", &a, &b);
    int ret = gcd(a, b); // 最大公因数
    printf("%d 和%d的最大公因数是:%d", a, b, ret);
    return 0;
}
2. 穷举法

法如其名,一个一个地输入测试,最后取出来。

#include <stdio.h>

int main() {
    int a = 0;
    int b = 0;
    scanf("%d %d", &a, &b);
    int t = a;
    while (t--) {
        if (a % t == 0 && b % t == 0) break;
    }
    printf("%d", t);
    return 0;
}
3. 递归法

简单来说,递归法其实就是模拟了辗转相除法。

#include <iostream>
using namespace std;

int gcd(int a, int b) {
    if (a % b == 0) {
        return b;
    } else {
        return gcd(b, a % b);
    }
}

int main() {
    int a, b;
    a = 18;
    b = 12;
    cout << gcd(a, b) << endl;
    return 0;
}

三、练习:等差数列最短项数

题目描述 数学老师给小明出了一道等差数列求和的题目。但是粗心的小明忘记了一部分的数列,只记得其中 N 个整数。 现在给出这 N 个整数,小明想知道包含这 N 个整数的最短的等差数列有几项?

输入描述 输入的第一行包含一个整数 N。 第二行包含 N 个整数 A1, A2, ..., AN。(注意 A1 ~ AN 并不一定是按等差数列中的顺序给出) 其中,2 ≤ N ≤ 10^5,0 ≤ Ai ≤ 10^9。

输出描述 输出一个整数表示答案。

这道题目难度适中,关键在于利用最大公约数求解公差。

  1. 很多人不会想到用 GCD 解题,甚至直接暴力解题。但可以利用最小差值作为间隔。
  2. 核心思路是求出所有相邻元素差值的最大公约数,即为公差 d。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

// 通过递归求最大公约数
int gcd(int a, int b) {
    if (a % b == 0) {
        return b;
    } else {
        return gcd(b, a % b);
    }
}

int main() {
    int n;
    cin >> n;
    vector<int> vec(n);
    for (int i = 0; i < n; ++i) {
        cin >> vec[i];
    }

    if (vec.size() == 2) {
        // 特殊情况,只有两个数
        cout << 2 << endl;
        return 0;
    }

    sort(vec.begin(), vec.end());
    
    vector<int> dif(n - 1);
    // 差集数列
    for (int i = 0; i < vec.size() - 1; ++i) {
        dif[i] = vec[i + 1] - vec[i];
    }

    int d = dif[0];
    if (d == 0) {
        // 有没有一种可能,差值为 0(所有数相同)
        cout << n << endl;
        return 0;
    }

    // 所有差集的最大公约数即为公差
    for (int i = 1; i < dif.size(); ++i) {
        d = gcd(d, dif[i]);
    }

    int num = (vec[vec.size() - 1] - vec[0]) / d;
    // d 为 0 的情况,已经被排除
    if (num == 0) {
        cout << vec.size() << endl;
    } else {
        cout << num + 1 << endl;
    }
    return 0;
}

总结

学习数论的一系列算法时,往往直接看算法是看不懂的。需要先摸清数学思想,胸有成竹之时,写对应算法就更轻松、也记得更牢固。别人算法理解不透的时候,往往是基础扎的不够牢固。

目录

  1. 一、什么是公约数
  2. 补充:最小公倍数 (LCM)
  3. 二、计算最大公约数的方法
  4. 1. 辗转相除法(欧几里得算法)
  5. 数学原理
  6. 代码实现
  7. 2. 更相减损版(辗转相减法)
  8. 数学原理
  9. 代码实现
  10. 3. 其他方法
  11. 1. 分解质因数
  12. 2. 穷举法
  13. 3. 递归法
  14. 三、练习:等差数列最短项数
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • C语言指针与数组的深度应用与内存解析
  • Python 实现 JSON 转 CSV:基础与嵌套数据处理
  • Windows Git 安装全流程与配置指南
  • HarmonyOS6 RcImage 组件核心架构与状态管理机制
  • 前缀和算法详解:高效解决区间求和问题
  • ChatGPT 记忆功能揭秘:使用与管理指南
  • 投资策略规划最优决策分析
  • 前端核心面试题解析:闭包、事件循环与 Vue 原理
  • 6 款免费 AI 写作软件测评及网文创作辅助指南
  • WebGIS + 无人机 + AI:智能巡检系统架构设计
  • llama.cpp CUDA 编译与性能优化实战指南
  • TK X-Gnarly:基于 AI 辅助的 JSVMP 纯算还原方案
  • Python 机器学习数据预处理:五种常用方法案例详解
  • MATLAB Simulink 仿真三相桥式全控整流电路
  • 基于 FastGPT 与 MCP 协议构建工具增强型智能体
  • 豆包·图像创作模型 Seedream 4.0 评测与功能实战
  • 2026 年 AI 行业趋势深度报告
  • Python 3.12.0 在 Windows 系统下的安装与配置指南
  • JavaSE 入门:注释、方法、基础数据类型与输入输出
  • 本地大模型部署的残酷真相:成本、门槛与体验落差

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online