乘法逆元的 exgcd 求法

乘法逆元的 exgcd 求法

乘法逆元

对于一个整数 a a a,它的逆元 d d d 等于 a − 1 a^{-1} a−1。

显然有 a d = 1 ad=1 ad=1。

在 OI 中,大部分情况都是对一个整数 p p p 进行取模的情况下求逆元。

即求出满足 a d ≡ 1 (   m o d   p ) ad\equiv 1(\bmod p) ad≡1(modp) 的 d d d。

费马小定理求法与扩展欧几里得求法

费马小定理求法

这种求法仅限于 p p p 是一个质数的情况下。

费马小定理:对于质数 p p p 和任意整数 a a a,有 a p − 1 ≡ 1 (   m o d   p ) a^{p-1}\equiv 1(\bmod p) ap−1≡1(modp)。

所以令 d = a p − 2 d=a^{p-2} d=ap−2,一定有 a d = a × a p − 2 = a p − 1 ≡ 1 (   m o d   p ) ad=a\times a^{p-2}=a^{p-1}\equiv 1(\bmod p) ad=a×ap−2=ap−1≡1(modp)。

这里用快速幂用 log 的时间随便求求就好了。本文的重点不在这里。

扩展欧几里得

扩展欧几里得,简称 exgcd。用到了普通 gcd 的性质。

gcd 的性质: gcd ⁡ ( a , b ) = gcd ⁡ ( b , a   m o d   p ) \gcd(a,b)=\gcd(b,a\bmod p) gcd(a,b)=gcd(b,amodp)。

扩展欧几里得算法是求解类似于给定 a , b a,b a,b,求 a x + b y = gcd ⁡ ( a , b ) ax+by=\gcd(a,b) ax+by=gcd(a,b) 的一组可行解 ( x , y ) (x,y) (x,y)。

先来看看这个式子与乘法逆元有什么关系。
a x ≡ 1 (   m o d   p ) a x − 1 ≡ 0 (   m o d   p ) ax\equiv 1(\bmod p)\\ ax-1\equiv 0(\bmod p)\\ ax≡1(modp)ax−1≡0(modp)

所以我们设 a x − 1 = k p ax-1=kp ax−1=kp。其中 k k k 是一个整数。

那么式子又变成了:
a x − 1 = k p a x − k p = 1 ax-1=kp\\ ax-kp=1 ax−1=kpax−kp=1

我们令 b = p , y = − k b=p,y=-k b=p,y=−k,就可以转化为 a x + b y = 1 ax+by=1 ax+by=1 的情况了。

所以我们只要解出 a x − k p = 1 ax-kp=1 ax−kp=1 这个方程,就得到了 x x x。它就是我们所求的答案。

注意其实 y y y 并不重要。

然后我们讨论如何求类似于这一类的方程。

根据上文的公式 gcd ⁡ ( a , b ) = gcd ⁡ ( b , a   m o d   b ) \gcd(a,b)=\gcd(b,a\bmod b) gcd(a,b)=gcd(b,amodb),如果我们知道了在 gcd ⁡ ( b , a   m o d   b ) \gcd(b,a\bmod b) gcd(b,amodb) 情况下的解 ( x ′ , y ′ ) (x',y') (x′,y′),就显然有 b x ′ + ( a   m o d   b ) y ′ = 1 bx'+(a\bmod b)y'=1 bx′+(amodb)y′=1。

而 a   m o d   b a\bmod b amodb 又可以转化为 a − ⌊ a b ⌋ b a-\lfloor\frac{a}{b}\rfloor b a−⌊ba⌋b。

所以原式又有:
b x ′ + ( a − ⌊ a b ⌋ b ) y ′ = 1 b x ′ + a y ′ − ⌊ a b ⌋ b y ′ = 1 a y ′ + b ( x ′ + ⌊ a b ⌋ y ′ ) = 1 bx'+(a-\lfloor\frac{a}{b}\rfloor b)y'=1\\ bx'+ay'-\lfloor\frac{a}{b}\rfloor by'=1\\ ay'+b(x'+\lfloor\frac{a}{b}\rfloor y')=1 bx′+(a−⌊ba⌋b)y′=1bx′+ay′−⌊ba⌋by′=1ay′+b(x′+⌊ba⌋y′)=1

所以可以得出 x = y ′ , y = x ′ + ⌊ a b ⌋ y ′ x=y',y=x'+\lfloor\frac{a}{b}\rfloor y' x=y′,y=x′+⌊ba⌋y′。

于是就可以递归下去求答案了。

那么对于递归的尽头,即当 b = 0 b=0 b=0 时, a x + 0 y = gcd ⁡ ( a , 0 ) = a ax+0y=\gcd(a,0)=a ax+0y=gcd(a,0)=a 时,令 x = 1 x=1 x=1, y y y 取任何恰当的值即可。别整什么 2147483647 2147483647 2147483647 之类的作死行为就好。

哦对, y y y 建议是个非负数,比如 0 0 0、 1 1 1 之类的都挺不错。如果你取个 − 1 -1 −1 之类的,最后算出来可能要多次取模,十分麻烦。

例题

link

代码:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ljl;
ljl a,b,ans,t;//t就是来打酱油的
void exgcd(ljl a,ljl b,ljl &x,ljl &y)
{
	if(!b)
	{
		x=1;y=0;
		return;
	}
	exgcd(b,a%b,x,y);
	ljl tx=x;
	x=y;y=tx-a/b*y;
	return;
}
int main(){
	ios::sync_with_stdio(0);
	cin>>a>>b;
	exgcd(a,b,ans,t);
	cout<<(ans+b)%b<<'\n';//这里注意的ans可能是个负数,要取模
	return 0;
}
相关推荐
rockey6273 小时前
AScript如何实现中文脚本引擎
c#·.net·script·eval·expression·function·动态脚本
wuweijianlove3 小时前
算法性能的渐近与非渐近行为对比的技术4
算法
研究点啥好呢4 小时前
Github热门项目推荐 | 创建你的像素风格!
c++·python·node.js·github·开源软件
_dindong4 小时前
cf1091div2 C.Grid Covering(数论)
c++·算法
AI成长日志4 小时前
【Agentic RL】1.1 什么是Agentic RL:从传统RL到智能体学习
人工智能·学习·算法
沫璃染墨4 小时前
C++ string 从入门到精通:构造、迭代器、容量接口全解析
c语言·开发语言·c++
黎阳之光4 小时前
黎阳之光:视频孪生领跑者,铸就中国数字科技全球竞争力
大数据·人工智能·算法·安全·数字孪生
skywalker_114 小时前
力扣hot100-3(最长连续序列),4(移动零)
数据结构·算法·leetcode
6Hzlia4 小时前
【Hot 100 刷题计划】 LeetCode 17. 电话号码的字母组合 | C++ 回溯算法经典模板
c++·算法·leetcode
_李小白4 小时前
【OSG学习笔记】Day 38: TextureVisitor(纹理访问器)
android·笔记·学习