拓展欧几里得 到 乘法逆元 (+线性求法) 个人解释 + 普通模板

深入解析乘法逆元:从模运算除法到算法实现与应用 在模运算中,除法无法直接进行,这引出了乘法逆元的核心概念。乘法逆元本质上是模运算下的‘倒数’,它使得在模数m下,a与其逆元x的乘积模m等于1,即a*x ≡ 1 (mod m)。其存在的充要条件是a与m互质,这可以通过贝祖定理进行严格证明。理解乘法逆元的技术价值在于,它为解决模运算中的除法问题提供了通用方案,是连接数论基础与工程实践的关键桥梁。在应用场景上,乘法逆元是算法竞赛中组合数取模、分数取模计算的基石,也是密码学(如RSA算法)和数据校验等领域的基础工具。本文将以扩展欧几里得算法、费马小定理和线性递推法 阅读详情

话说PION初赛 (本月13号) 要到了我还是得弄一下不然连50分都没有...........

 

首先我们要知道欧几里得是什么——某求最小公约数 (gcd) 的东西 这个东西如果不知道......那我真没办法

好了那拓展欧几里得是什么呢?就是 extendgcd 俗称 exgcd

好吧其实名称是没luan用的 我们来看看这东西的用处

然而只是用来求 ax + by = gcd(a,b) 的?当然 但是有许多其他式子 (我也没找几个) 如 ax ≡ 1 (mod b) 就可以转化为那个

好吧这就是我这篇要讲的题 链接丢这里先 后面再放一个

ax ≡ 1 (mod b) 转化一下就是 ax mod b ≡ 1

仔细想想 ax mod b 就是 ax ÷ b 取余

也就是 ax - b * (ax / b ( / 用来取整) ) = 1 然而这样并不好求 我们设和 b 乘起来的一大坨东西为 y 则有

ax - by = 1 也就是 ax + (-by) = 1 诶这里 y 是个负数耶 然而并不关我们的事 谁说负数就求不了了呢?注意了 这里有伏笔

我们已经转化到了 ax + by 的形式 所以原式就是要 ax + by = 1 那我们就可以很容易发现

gcd(x,y) = 1 !!!没错!!!我们的拓展欧几里得可以派上用场了

好吧拓展欧几里得是什么都没说呢 现在开始讲解就是一个式子啦要讲什么嘛 我直接推导然后应用就好了 (其实要讲的就是这些 讲完以后就懂了) 诸客官请看下面

欧几里得是干嘛的?辗转相除 (好像听说过相减不过这边我们不管) 嘛

拓展欧几里得呢?肯定也是一样的尿性嘛 用辗转相除 有什么用呢 啊哈

因为这里 gcd = 1 所以 x 和 y 的最大公约数为 1 通过普通欧几里得可以发现 此时两数 1 个是 1 另一个是 0

然后拓展欧几里得里如果知道了这些 那我们就少了两个未知数 然后这题 a 和 b 又知道 那完全就没有未知数了嘛

然后我们回溯就好了呀~~ 好吧证明一下可行性

首先

ax   +    by    = gcd(a,b)
ax'  + (b % a)y'= gcd(a,b % a)

显然 gcd(a,b) = gcd(a,b % a)
所以 ax + by = ax' + (b % a)y'
那我们根据欧几里得最后就得到了 x = 1,y = 0

于是次数方程变成 1 * a + 0 * b = gcd(a,b) = a
这推到底的解就出来了

那我们考虑推回去 因为上一层的 a = a,b = b % a
哦不 欧几里得的辗转相除每层的 a 和 b 都是反过来的
因为两个数的大小问题 b > a 但是 b % a < a 要反过来
所以应该是 b = a,a = b % a

但是我们要求的是 x 和用来辅助的 y
记得有个叫乘法交换律的东西吧
那我们就不变 a 和 b 变 x 和 y 像推 a 和 b 一样
然后利用每层递归的 a 和 b 的值 就可以找到原来的 x 和 y 了
但原来的那个是一个特解 如果像本题一样找最小的 就要像下面代码一样
如果找第 k 小的 就用最小解乘上 k 就好啦

下放代码 隔开方便复制 题目链接戳这里

#include <cstdio>
using namespace std;
int x,y;
void exgcd(int a,int b)
{
	if (!b) {x = 1,y = 0; return;}
	exgcd(b,a % b);
	int bot = x;
	x = y;
	y = bot - a / b * y;
}
int main()
{
	int a,b;
	scanf("%d%d",&a,&b);
	exgcd(a,b);
	printf("%d\n",(x % b + b) % b);
	return 0;
}
/*Frocean用 a b 只做循环变量~~
#include <cstdio>
using namespace std;
int i,j;
void exgcd(int x,int y)
{
	if (!y) {i = 1,j = 0; return;}
	exgcd(y,x % y);
	int bot = i;
	i = j;
	j = bot - x / y * j;
}
int main()
{
	int x,y;
	scanf("%d%d",&x,&y);
	exgcd(x,y);
	printf("%d\n",(i % y + y) % y);
	return 0;
}
*/

 

拓展欧几里得的这种用法 又可以说是求乘法逆元 不过乘法逆元的定义可能和上面那式子不太一样

若 a * x \equiv 1 (mod b) 且 a 与 b 互质,那么 x 为 a 的逆元 x 也可表示为 a^{-1} 也称 x 为 a 的倒数

( 后面讲的时候 b 换成 p 因为题目原因 )

就像上面那个求就好了 但注意一点

    比如说 4 * 3 在 mod 11 的意义下 3 是 4 的乘法逆元
    然而 4 * 14 在 mod 11 的 意义下 14 也是 4 的乘法逆元
    但是 14 在 mod 11 意义下 就是 3 因为 14 = 11 + 3
    所以如果要求乘法逆元 输出的只有一个

好了好了 就像上面那程序一样就求得出来了 完全一样

但如果我们要求线性的解呢?比如这道题目 像上面那样一个个跑绝对会炸掉的

那我们就需要线性算法 这个要推一个式子

 

首先 1 的乘法逆元肯定要先弄出来 很显然 1^{-1} = 1 了 也就是 1^{-1} \equiv 1 (mod p) 且当 p>1 时

还有一个前提条件 线性算法只能求 p 为质数时 1 ~ p - 1 的乘法逆元

因为这个条件 我们设 p 是由一堆数构成的 因为 p 又是质数 所以要分解成 k 倍的 i + r 的形式

即 p = k * i + r,r < i,1 < i < p 其中 r < i 是因为 r ≥ i 时 r 可以化成 i 的 倍数

指定 i 为当前需要求的数 则其乘法逆元为 i^{-1}

我们可由 p mod p = 0 得到一个式子

 k * i + r \equiv 0 (mod p)

接下来转化 同乘 i^{-1}r^{-1} (就是同除ir) 得

 k * r^{-1} + i^{-1} \equiv 0 (mod p)

i^{-1} \equiv - k * r^{-1} (mod p)

此时将右边两项分开 k = p / i 并且 r = p mod i 此时指数不变 见下

i^{-1} \equiv - \left \lfloor \frac{p}{i} \right \rfloor * (p mod i)^{-1} (mod p)

此时 (p mod i)^{-1} 是 p mod i 这个数的逆元 这个数必定小于 i 因此我们早已求出

这时候我们可以得到第一种式子

ans [ i ] = - p / a * ans [ p % a ] % p

然而这个式子是错的 因为会有负数 所以要改成下面那样 原理和上面拓展欧几里得的代码一样

ans [ i ] = ( ( - p / a * ans [ p % a ] ) % p + p) % p

然后这样就可以跑了 实测556ms(当然要开long long)

下放代码

#include <cstdio>
#define ll long long
const int MAXN = 3000010;
int ans[MAXN],n,p;
int main()
{
    ans[1] = 1; scanf("%d%d",&n,&p);
    for (int i = 2 ; i <= n ; ++ i)
		ans[i] = ((- (ll)p / i * ans[p % i]) % p + p) % p;
    for (int i = 1 ; i <= n ; ++ i)
		printf("%d\n",ans[i]);
    return 0;
}

 

还有 其实我们可以继续推下去

看一下我们之前的 - \left \lfloor \frac{p}{i} \right \rfloor 通俗一点就是 - \frac{p}{i} 看好了 在 mod p 意义下 这个项和下面那个项相等——

p - \frac{p}{i} (mod p)

为什么呢?

因为我们可以先把前面的 p mod p 就是 0 那下面那个式子就变成 - \frac{p}{i} 了

众所周知 除 比 取模 要快上一些

于是我们可以得出下面这个式子

ans [ i ] = ( p - p / i ) * ans [ p % a ] % p

于是我们拿下面这个式子跑 实测470ms(当然要开long long)

下放代码

#include <cstdio>
#define ll long long
const int MAXN = 3000010;
int ans[MAXN];
int main()
{
	int n,p;
	ans[1] = 1;
	scanf("%d%d",&n,&p);
	for (int i = 2 ; i <= n ; ++ i)
		ans[i] = (ll)(p - p / i) * ans[p % i] % p;
	for (int i = 1 ; i <= n ; ++ i)
		printf("%d\n",ans[i]);
	return 0;
}

 

信奥数论题必胜心法:扩展欧几里得与费马小定理求逆元实战 在信息学竞赛与算法实践中,模运算是处理大数计算的核心基础。其原理在于通过取余操作将无限整数域映射到有限集合,从而避免数值溢出。掌握模运算对于实现高效、正确的算法至关重要,尤其在需要处理除法时。在模意义下,除法需转化为乘法逆元运算,这直接关系到组合数学、密码学等场景的计算准确性。扩展欧几里得算法通过求解贝祖等式通用地计算逆元,而费马小定理则在模数为质数时提供了基于快速幂的简洁实现。本文以信奥典型数论题为背景,深入剖析这两种方法的原理、C++实现细节与避坑指南,帮助读者构建解决模除问题的‘必胜’代码框架,并自然 阅读详情

相关推荐

LeetCode刷题实战:用扩展欧几里得算法秒解‘同余方程’类题目

本文详细介绍了如何使用扩展欧几里得算法高效解决LeetCode中的同余方程问题。通过算法原理讲解、模板代码实现及典型例题分析,帮助读者掌握这一数论核心技巧,提升算法竞赛和面试中的解题能力。

weixin_30607029的博客 481

逆元在算法竞赛中的高效应用:从理论到实战

本文深入解析了算法竞赛中逆元的核心概念与高效应用。针对模运算下的除法难题,详细介绍了扩展欧几里得算法、费马小定理结合快速幂以及线性递推打表这三种主流求解方法,并分析了各自的适用场景与实战技巧。通过组合数计算等经典例题,展示了如何利用逆元将模意义下的除法转化为乘法,从而安全高效地解题,是提升数论竞赛能力的必备知识。

weixin_29047919的博客 394

组合数高效计算:预处理与逆元优化实现O(1)查询

组合数计算是算法竞赛与面试中的基础数论问题,其核心在于模运算下的高效求解。直接套用公式C(n,m)=n!/(m!*(n-m)!)在模运算下会因除法不满足模运算规则而失效,需引入乘法逆元将除法转化为乘法。利用费马小定理与快速幂可求逆元,但单次查询仍需O(log p)时间。通过预处理阶乘数组fact[i]与阶乘逆元数组infact[i],可将查询复杂度降至O(1),实现海量查询的快速响应。这种预处理思想是典型的空间换时间策略,适用于需要频繁查询固定范围函数值的场景,如组合数、斐波那契数列等。本文以AcWing

weixin_33901641的博客 330

扩展欧几里得算法求逆元---乘法密码

背景知识: 欧几里得算法:又叫做辗转相除法,用来求两个数的最大公约数。通过辗转相除,当余数为0的时候,最后的除数就是两个数的最大公约数。 例如:求20和11的最大公约数 每次将除数作为下一个式子的被除数,将余数作为下一个式子的除数。 20➗11=1......9 11➗9=1......2 9➗2=4......1 2➗1=2......0 所以最大公约数为最后一个式子的除数1,即gcd(20,11)=...

HPU_FRDHR的博客 6857

CST微波工作室端口设置保姆级教程:从波导端口到离散端口,手把手教你搞定S参数仿真

本文提供CST微波工作室端口设置的详细教程,涵盖波导端口和离散端口的选择与配置,助力工程师精准完成S参数仿真。通过微带线滤波器案例,详解端口尺寸、阻抗设置及常见问题排查,提升仿真效率与准确性。

weixin_42570296的博客 358

Windows环境下pcl点云库 安装配置全流程(精简、有效)

本文为Windows配置点云库pcl步骤,具体是win10、visual studio 2017、pcl1.11.1。

zaibeijixing的专栏 1万+

扩展欧几里得算法(求逆元)

前论 1. 欧几里得算法 欧几里德算法又称辗转相除法,用于计算两个整数a,b的最大公约数。 gcd函数就是用来求(a,b)的最大公约数的。 gcd函数的基本性质: gcd(a,b)=gcd(b,a)=gcd(-a,b)=gcd(|a|,|b|) 公式表述 gcd(a,b)=gcd(b,a mod b) 证明: a可以表示成a = kb + r,则r = a mod b 假设d...

QAQ 9069

AB相增量式编码器以及STM32定时器编码器模式测速/测距离(HAL库)

编码器(Encoder)是一种用于测量旋转运动或位置的设备。编码器通常与定时器模块一起使用,以便在微控制器中获取和计算旋转的脉冲数量,从而确定物体的运动方向和距离。编码器在许多应用中都很有用,例如机器人运动控制、电机位置反馈和位置传感。STM32微控制器提供了多种类型的编码器支持,其中一种常见的编码器类型是增量编码器。增量编码器基于两个脉冲信号通道,通常称为A相和B相。当旋转发生时,这两个信号通道的相位关系会发生变化,从而可以计算出旋转方向和旋转的步数。

嵌入式软件工程师的博客 1万+

扩展欧几里得算法(求逆元)总结

1、在RSA算法生成私钥的过程中涉及到了扩展欧几里得算法(简称exgcd),用来求解模的逆元。 2、首先引入逆元的概念: 逆元是模运算中的一个概念,我们通常说 A 是 B 模 C 的逆元,实际上是指 A * B = 1 mod C,也就是说 A 与 B 的乘积模 C 的余数为 1。可表示为 A = B^(-1) mod C。 打个比方,7 模 11 的逆元,即:7^(-1) ...

azx59285的博客 1万+

雷电模拟器+Google Play服务配置全指南:从安装到定位问题解决

本文详细介绍了雷电模拟器配置Google Play服务的全流程,包括版本选择、组件安装、定位服务调试及网络问题排查。针对安卓开发者的常见挑战,提供从基础到高级的解决方案,帮助优化测试环境稳定性与定位精度。

weixin_30399821的博客 1219

W5500+STM32F103C8T6进行TCP通信(modbus)

一路生花一、w5500资料二、modbus通信三、从机代码四、总结五、参考 一、w5500资料 w5500的资料就放在下面了,单纯的客户端和其他模式上面有教程 https://www.aliyundrive.com/s/enPnnZgNtpE 二、modbus通信 Modbus RTU通信时使用的数据帧结构如下图,而Moubus TCP通信的数据帧和这个稍微不一样,没有crc检验,因为tcp本就是一种可靠传输协议 这里是Modbus TCP数据帧 公共功能码定义 三、从机代码

junseven164的博客 5777

扩展欧几里得算法(求逆元)

扩展欧几里得算法(求逆元)总结 1、在RSA算法生成私钥的过程中涉及到了扩展欧几里得算法(简称exgcd),用来求解模的逆元。 2、首先引入逆元的概念: 逆元是模运算中的一个概念,我们通常说 A 是 B 模 C 的逆元,实际上是指 A * B = 1 mod C,也就是说 A 与 B 的乘积模 C 的余数为 1。可表示为 A = B^(-1) mod C。 打个比方,7 模 11 的逆元,即:7^(-1) mod 11 = 8,这是因为 7 × 8 = 5 × 11 + 1,所以说 7 模 1.

zw201909250425的博客 2万+

C++ PCL点云处理实战专栏

工业级点云处理技术学习资源,涵盖电力、建筑、隧道等领域的实战案例。内容分为三阶段:代码原理(算法认知)、动态库(项目验证)和完整代码(定制开发)。

weixin_45196569的博客 1117

密码学基础-扩展的欧几里得算法求乘法逆元

一、先理解几个定义 规定定义在正整数上的二元函数gcd(a, b)(a≥b)表示正整数a和正整数b的最大公约数,例如:gcd(6,3)=3, gcd(7,4)=1.运算mod表示模数运算,例如5 mod 3 = 2, 或者 5 = 2 (mod 3) 欧几里德有个十分又用的定理: gcd(a, b) = gcd(b , a%b) ,这样,我们就可以在几乎是 log 的时间复杂度里求解出来 a 和 b 的最大公约数了,这就是欧几里德算法。例如:gcd(15750, 27216) = gcd(15750, 1

weixin_46866349的博客 1万+

Linux 下 OpenClaw 安装全记录:从零到一的保姆级图文教程

本文主要介绍了Linux 下 OpenClaw 安装全记录:从零到一的保姆级图文教程,希望能对学习使用OpenClaw 的同学们有所帮助。 文章目录 1. 背景 2. 实战教程 2.1 步骤一 安装Node.js 2.2 步骤二:安装git 2.3 步骤三:安装并配置OpenClaw 2.4 步骤四:配置OpenClaw 2.5 步骤五:配置模型 2.6 步骤六:对话 3. 后续使用步骤 4. 报错解决方案 5. OpenClaw的卸载

weixin_43178406的博客 10万+

【原理图与PCB专题】使用Cadence如何在Layout时直接互换相同功能的PIN

Cadence允许我们在PCB中互换管脚,最后再反标给原理图。集成TVS管、排阻、DDR、FPGA有一些PIN是完全相同功能,可进行管脚互换的,建议使用这个功能。可降低硬件工程师与Layout工程师之间沟通成本,加快设计进度。

一点硬件 801

【模板】非质模数下的乘法逆元【牛客tracker & 每日一题】

本文介绍了在非质数模数下求解乘法逆元的方法。题目要求对于给定的正整数对(a,m),计算a的乘法逆元a⁻¹ mod m。由于模数m不一定是质数,无法使用费马小定理,而需要采用扩展欧几里得算法。 核心思路是将逆元问题转化为求解线性同余方程ax ≡ 1 mod m,这等价于求解方程ax + my = 1。通过扩展欧几里得算法可以同时求出gcd(a,m)和方程的解x。当gcd(a,m)=1时,逆元存在,通过调整解x的范围得到最终结果;否则逆元不存在。 算法时间复杂度为O(log min(a,m)),能够高效处理大规

Pretty Boy Fox的博客 403

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

拓展欧几里得总结(模板)+CSU 1941

六天的暑假结束啦,我终于回归啦……         第一天,先把之前没做完的题目做完吧。嗯,拓展欧几里得,按理说早就该学的,但是一直拒绝数论……         首先,拓展之前先说说普通欧几里得算法。就是著名的辗转相除法,几个同余定理。而拓展欧几里得就是利用欧几里得定理求线性方程ax+by=c的通解。要解这个方程的通解,其实一开始是求方程ax+by=gcd(a,b)的解,再转化过去的。求解方程ax+by=gcd的特解就是拓展欧几里得算法的作用,具体原理我就不在这里说了,知道特解后,它的通解形式如下:x=x0

alpc_qleonardo 586

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

[python刷题模板] 取模技巧/组合数取模模板/快速幂取模模板

卢卡斯定理好难!

liuliangcan的博客 913

数论基础的补充讲解

数论基础的补充讲解 整除的一些性质: (1)能被2整除的数,个位上的数都能被2整除 (2*)能被4整除的数,个位和十位所组成的两位数能被4整除 (3*)能被8整除的数,百位、十位和个位所组成的三位数能被8整除 (4)能被5整除的数,末尾是0或5 (5*)能被25整除的数,十位和个位所组成的两位数能被25整除 (6*)能被125整除的数,百位、十位和个位所组成的三位数能被125整除

Fighting! 3415

蓝桥杯算法竞赛核心数论模板精讲:从gcd到扩展欧几里得

在算法竞赛和编程实践中,数论是解决复杂问题的关键基础。其核心概念如最大公约数(GCD)和模运算,不仅是理解整数性质的基石,更是构建高效算法的原理所在。通过欧几里得算法及其扩展形式,我们能够在对数时间内求解最大公约数和线性同余方程,这一技术价值在于将看似复杂的整数关系转化为可计算模型。在算法竞赛(如蓝桥杯)和加密算法(如RSA)等应用场景中,快速幂算法和欧拉函数常与这些基础理论结合,用于处理大数取模和模逆元计算。本文聚焦于**欧拉函数**和**快速幂**这两个热词,深入剖析其底层逻辑、线性筛法实现及常见避坑指

weixin_29032489的博客 241

数论模板及推理过程

算法竞赛中的数论模板以及推论

qq_52765554的博客 1513

数论基础知识和模板

单位元:在一个集合中,对于某种运算∗,如果对于任何的集合元素 a,和元素 e 运算,得到还是集合元素 a 本身,则称 e 为这个运算下的单位元。实现就是,对于每个数,我们都将他对整个现在已有的质数表筛一遍,比如3是质数,那么把已有的2相乘,筛掉6,但是并不往下进行,因为比如12,最小质数因数是3,在遍历到4时自然而然就筛掉了,这样每个数就只会被他最小质因数筛掉一次,达到了线性。为了保证逆元是正数,我们把公式调整为 i−1≡(p−k)×r−1(modp),这里的 r 其实就是 p%i。vis[j] = 1;

ysa051030的博客 977

[模板]数学整合

数学整合:为10天后的考试准备! 1.1:欧几里得算法(位运算)    目前接触到的最快的求GCD的算法,而且不算太长,值得一记(虽然没有什么题目卡GCD吧。。。) 1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<algorit...

weixin_30780649的博客 117

数论算法精讲:快速幂、扩展欧几里得与欧拉降幂原理与应用

在算法竞赛与密码学实践中,模运算与数论算法是处理大数计算的核心基础。其核心原理在于利用模运算的代数性质,将复杂的整数运算约束在有限域内,从而在保证结果正确性的前提下,大幅提升计算效率并避免数值溢出。这一技术价值在于为RSA加密、离散对数问题等现代密码学基石提供了可行的计算工具,同时也是解决动态规划中状态转移优化等高性能计算场景的关键。具体到应用场景,当需要高效计算a的b次方对m取模时,快速幂算法通过二进制分解将复杂度降至对数级;而在求解模线性方程或计算模逆元时,扩展欧几里得算法则不可或缺;当指数b本身也极大

weixin_34067102的博客 520
上一篇: JZOJ 5060【GDOI2017第二轮模拟day1】公路建设
下一篇: JZOJ 5904【NOIP2018模拟10.15】刺客信条
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值