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

竞赛小算法总结(二):gcdlcm,拓展欧几里得线性同余,逆元(含代码详解)

一 gcd&lcm 

这个其实也属于是很简单但非常有必要掌握的小算法。

1. 定义

“gcd” 是 “Greatest Common Divisor” 的缩写,中文名为最大公约数 ,也称最大公因数。它指的是两个或多个整数共有约数中最大的一个。例如,对于整数 12 和 18 ,12 的约数有 (1, 2, 3, 4, 6, 12) ,18 的约数有 (1, 2, 3, 6, 9, 18) ,它们共有的约数有 (1, 2, 3, 6) ,其中最大的是 6 ,所以 12 和 18 的最大公约数(gcd )是 6 ,可表示为 (gcd(12, 18)=6) 。

2. 计算方法

这个其实也不用完全死记,大概记住现场也可以推一下。

下面是代码

/*** 使用辗转相除法计算两个整数的最大公约数(GCD)。* 原理:对于任意两个整数a和b,gcd(a, b) = gcd(b, a mod b),* 不断重复此过程直到余数为0,此时的除数即为最大公约数。* * @param a 第一个整数* @param b 第二个整数(不能为0,否则会导致除零异常)* @return a和b的最大公约数*/
public static int gcd(int a, int b) {// 计算a除以b的余数int k = a % b;// 当余数为0时,当前的除数b就是最大公约数if (k == 0) {return b;}// 否则递归计算b和余数k的最大公约数return gcd(b, k);
}

 lcm就是最小公倍数,我们直接a*b/gcd(a,b)就可以了。

代码:

public static int lcm(int a,int b) {return a*b/gcd(a,b);}

二 拓展欧几里得&线性同余

拓展欧几里得算法(Extended Euclidean Algorithm)

基本定义 拓展欧几里得算法是欧几里得算法(辗转相除法)的扩展,不仅能计算两个整数 a 和 b 的最大公约数 (d = gcd(a, b)),还能找到整数 x 和 y,使得:ax + by = d其中,x 和 y 被称为 贝祖系数(Bézout coefficients)。

贝祖系数一般用于求解求解线性不定方程ax + by = d,题目可能设计成以这个为原理的故事算法题,还有就是第三部分要讲的求模逆元。

下面来看怎么求贝祖系数:

在计算gcd时进行回溯。

// 扩展欧几里得算法 - 递归实现public static long[] extendedGCD(long a, long b) {if (b == 0) {// 终止条件:gcd(a, 0) = a,对应的贝祖系数为 (1, 0)return new long[]{a, 1, 0};} else {// 递归计算 gcd(b, a mod b)long[] result = extendedGCD(b, a % b);//接受上一层的返回值long gcd = result[0];long x = result[2];long y = result[1] - (a / b) * result[2];return new long[]{gcd, x, y};}}

三 模拟元

逆元(模运算中的乘法逆元)

在模运算中,逆元(Multiplicative Inverse) 是一个核心概念,用于解决除法问题。对于整数 a 和模数 m,若存在整数 x 使得:

则称 x 为 a 在模 m 下的逆元。逆元存在的充要条件是 a 和 m 互质(即 gcd(a, m) = 1)。

1. 扩展欧几里得算法

当 a 和 m 互质时,通过扩展欧几里得算法求解 ax + my = 1,得到的 x 即为逆元。

 // 计算模逆元:若 a 和 m 互质,返回 a 在模 m 下的逆元;否则返回 -1public static long modInverse(long a, long m) {long[] result = extendedGCD(a, m);long gcd = result[0];long x = result[1];if (gcd != 1) {// a 和 m 不互质,逆元不存在return -1;} else {// 确保逆元在 [0, m-1] 范围内return (x % m + m) % m;}}

2. 费马小定理(当 m 为质数时)

代码: 

public static long powMod(long a, long b, long mod) {long result = 1;       // 初始化结果为1while (b > 0) {        // 循环直到指数b变为0if ((b & 1) != 0) { // 检查b的二进制最低位是否为1(等价于b % 2 != 0)result = result * a % mod; // 若为1,将当前底数a乘入结果并取模}a = a * a % mod;   // 底数平方并取模b >>= 1;           // 指数右移一位(等价于b /= 2)}return result;
}

讲实话,我碰到的最多的是gcd和lcm和逆元,逆元一般用于求含除数运算的数的模,如42!/2024%100000007。

 

http://www.xdnf.cn/news/683281.html

相关文章:

  • AE的ai图层导到Ai
  • spring4第2课-ioc控制反转-依赖注入,是为了解决耦合问题
  • WIN10 安装dify ollama搭建工作流agent
  • 两种主流检索技术:BM25(基于关键词匹配)和向量相似度检索
  • LVGL(Flex布局)
  • Docker修改镜像存放位置
  • qiankun 子应用怎样通过 props拿到子应用【注册之后挂载之前】主应用中发生变更的数据
  • vue2轮播图组件
  • 计算机网络实验课(二)——抓取网络数据包,并实现根据条件过滤抓取的以太网帧,分析帧结构
  • 如何检查液质联用仪LCMS的真空度
  • 提升前端性能:减少DOM操作
  • 在线项目管理工具对比:Trello、Worktile等20款软件测评
  • Java的Spring Cloud生态中实现SSE(Server-Sent Events)服务端实践
  • YoloV11改进策略:卷积篇-风车卷积-即插即用
  • 代码随想录算法训练营第60期第四十九天打卡
  • day05-常用API(二):Lambda、方法引用详解
  • Python装饰器与异常捕获的高级用法详解
  • 基于 STM32 的农村污水处理控制系统设计与实现
  • @vue/composition-api
  • uniapp-商城-72-shop(5-商品列表,购物车实现回顾)
  • Linux 6.15 内核发布,新功能
  • 【免费】【无需登录/关注】坐标系批量转换与可视化网页工具
  • 31. 自动化测试开发之实现INI配置文件解析
  • 从CPU缓存出发对引用池进行优化
  • C51-指针函数
  • Linux编译器——gcc/g++的使用
  • 基于Python的智能天气提醒助手开发指南
  • ValueError: BuilderConfig ‘xxxx‘ not found. Available:[xxx]
  • Cannot read properties of undefined (reading ‘clearSelection‘)
  • 华为仓颉语言初识:并发编程之线程的基本使用