当前位置: 首页 > news >正文

C语言:最大公约数

最大公约数(GCD)

是指能够同时整除两个或多个整数的最大正整数。

给定两个整数 aa 和 bb(不同时为0),它们的最大公约数 gcd⁡(a,b)gcd(a,b) 是满足以下条件的最大正整数 dd:

  • dd 能整除 aa(即 amod  d=0amodd=0)。

  • dd 能整除 bb(即 bmod  d=0bmodd=0)。

  • 对于任何其他满足前两个条件的 d′d′,有 d′≤dd′≤d。

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

原理gcd(a, b) = gcd(b, a % b),直到余数为0时,除数即为GCD。
特点:高效,时间复杂度为O(log(min(a, b)))。

int gcd(int a, int b) {while (b != 0) {int temp = b;b = a % b;a = temp;}return a;
}
  1. 循环条件while (b != 0)

    • 持续计算直到余数b为0,此时a即为GCD。

  2. 保存b的值int temp = b

    • 临时存储b,因为下一步b会被更新为余数。

  3. 计算余数b = a % b

    • a除以b,将余数赋给b

  4. 更新aa = temp

    • 将原来的b(保存在temp中)赋给a,继续下一轮计算。

  5. 返回结果return a

    • b=0时,a就是最大公约数。

 

2. 更相减损术(中国古法)

原理gcd(a, b) = gcd(a-b, b)(a > b),直到两数相等。
特点:避免取模运算,但效率较低(最坏O(max(a, b)))。

int gcd(int a, int b) {while (a != b) {if (a > b) a -= b;else b -= a;}return a;
}
  1. 循环条件while (a != b)

    • 持续相减直到两数相等。

  2. 减法操作

    • if (a > b) a -= b:若a大,则a = a - b

    • else b -= a:否则b = b - a

  3. 返回结果return a

    • a == b时,该值即为GCD。

注意事项
  • 效率问题:若两数相差极大(如gcd(1, 100000)),需循环多次,效率低于辗转相除法。

3. 递归实现(辗转相除法简化版)

代码简洁,但需注意栈溢出风险

int gcd(int a, int b) {return b == 0 ? a : gcd(b, a % b);
}
  1. 三元运算符b == 0 ? a : gcd(b, a % b)

    • 终止条件:若b=0,返回a

    • 递归调用:否则计算gcd(b, a % b)

  2. 递归过程

    • 每次递归将问题规模缩小,直到b=0

4. 二进制算法(Stein算法)

优化场景:适合大整数或硬件实现,避免乘除取模。
原理

  • 若a、b均为偶数:gcd(a, b) = 2 * gcd(a/2, b/2)

  • 若a为偶数:gcd(a, b) = gcd(a/2, b)

  • 其他情况用更相减损术。

    int gcd(int a, int b) {if (a == 0) return b;if (b == 0) return a;int shift = __builtin_ctz(a | b); // 公共的2的幂次数a >>= __builtin_ctz(a); // 移除a的2的因子do {b >>= __builtin_ctz(b); // 移除b的2的因子if (a > b) { int t = b; b = a; a = t; }b -= a;} while (b != 0);return a << shift;
    }
  1. __builtin_ctz(x)

    • GCC内置函数,返回x的二进制表示中末尾0的个数(即因子2的幂次)。

  2. 步骤解析

    • 步骤1:移除ab的所有公共2的因子(shift记录总次数)。

    • 步骤2:分别移除ab自身的2的因子。

    • 步骤3:用更相减损术计算奇数间的GCD。

    • 步骤4:将结果左移shift位(恢复公共的2的因子)。

优势
  • 避免乘除和取模运算,适合硬件实现或大整数计算。

5. 扩展欧几里得算法

额外功能:求解ax + by = gcd(a, b)的整数解(x, y)。

int extended_gcd(int a, int b, int *x, int *y) {if (b == 0) {*x = 1;*y = 0;return a;}int x1, y1;int gcd = extended_gcd(b, a % b, &x1, &y1);*x = y1;*y = x1 - (a / b) * y1;return gcd;
}
  1. 递归终止条件b == 0时,解为x=1, y=0(因a*1 + 0*0 = a)。

  2. 递归调用:计算gcd(b, a % b)并得到x1y1

  3. 解的组合

    • x = y1

    • y = x1 - (a / b) * y1

    • 满足方程:a*x + b*y = gcd(a, b)

应用场景
  • 求解模反元素(如RSA算法中的私钥)

 6.总结

  1. 数学基础

    • 欧几里得算法依赖定理:gcd(a, b) = gcd(b, a mod b)

    • 更相减损术与辗转相除法的等价性。

  2. 效率对比

    • 辗转相除法最优(尤其大数)。

    • 更相减损术适合硬件受限环境(无取模操作)。

  3. 边界条件

    • 处理负数:先取绝对值(如a = abs(a))。

    • 零值处理:gcd(a, 0) = |a|

  4. 实际应用

    • 分数化简、密码学(RSA算法)、线性同余方程求解。

  5. 进阶优化

    • 内联函数或宏定义加速小整数计算。

    • 使用位运算替代乘除(如Stein算法)。

 

http://www.lqws.cn/news/471205.html

相关文章:

  • 以AI赋能创意未来:即梦3.0与Seedance1.0Lite重磅登陆POE!
  • 操作系统内核态和用户态--2-系统调用是什么?
  • 新手如何利用AI助手Cursor生成复杂项目
  • LINUX621 NFS 同步 ;FTP;samba环境
  • 李宏毅2025《机器学习》第三讲-AI的脑科学
  • AI大模型学习之基础数学:微积分在AI大模型中的核心-梯度与优化(梯度下降)详解
  • FreeRTOS事件组(Event Group)
  • Rust调用 DeepSeek API
  • kibana和elasticsearch安装
  • Docker简单介绍与使用以及下载对应镜像(项目前置)
  • 《揭开CSS渲染的隐秘角落:重排与重绘的深度博弈》
  • 《Whisper:开启语音识别新时代的钥匙》
  • 【Redis】深入理解 Redis 事务:命令、应用与实战案例
  • SiteAzure:解决数据库服务器内存频繁吃满
  • 【Weaviate底层机制】分布式一致性深度解析:Raft算法与最终一致性的协同设计
  • PHP语法基础篇(五):流程控制
  • 给交叉工具链增加libelf.so
  • PowerShell读取CSV并遍历组数组
  • 在 `setup` 函数中实现路由跳转:Vue3与Vue Router 4的集成
  • 《Whisper模型版本及下载链接》
  • 网络钓鱼攻击
  • 【论文笔记】【强化微调】T-GRPO:对视频数据进行强化微调
  • [muduo] TcpConnection | 回调交互
  • LLM-201: OpenHands与LLM交互链路分析
  • Linux致命漏洞CVE-2025-6018和CVE-2025-6019
  • 1、自然语言处理任务全流程
  • 什么是redission看门狗机制
  • Redis 分布式锁、红锁分别是什么?红锁有什么问题?
  • Python漂浮的爱心
  • 【Ambari3.0.0 部署】Step2—免密登陆认证-适用于el8