扩展欧几里得算法与乘法逆元
Part 1:前置知识
-
欧几里得算法
-
定理对于任意整数
,存在一对整数 ,满足证明:
在欧几里得算法的最后一步,即
时,显然有一对整数 ,使得若
,则假设存在一对正整数
,满足则有
对欧几里得算法的递归过程应用数学归纳法,可知
定理 成立利用
定理,我们就可以使用 扩展欧几里得算法 来求出整数 的一组特解
Part 2:扩展欧几里得算法
1、求 的一组特解
- 代码
#define LL long long
LL exgcd(LL a,LL b,LL &x,LL &y)
{
if(b==0)
{
x=1; y=0;
return a;
}
LL d=exgcd(b,a%b,x,y);
LL tmp=x;
x=y; y=tmp-(a/b)*y;
return d;
}
2.求 的通解
-
已知
是一组特解, (下面的 含义相同) -
那么方程通解为
证明:
设 是除 之外的一组解则可得:
得:对
进行分析:对
分析,同理可得:
3.求 的解
-
对于一般的方程
,它有解当且仅当 -
通过先前的扩欧,我们可以求出方程
的一组特解 ,然后令 同时乘上 ,就得到了 的一组特解: -
由于
是 的倍数,所以类比求 的通解的过程,我们可以将 的通解表示为:
Part 3:乘法逆元
1. 定义
- 若整数
互质,且 ,那么就称 为 的模 乘法逆元。(记为 )
2.扩展欧几里得算法求逆元
-
将
变形可得: -
使用扩欧可轻松求出
的一个特解 -
若要求最小最小正整数解,则令
-
代码
void exgcd(int a,int b,int &x,int &y)
{
if(b==0)
{
x=1; y=0;
return;
}
exgcd(b,a%b,x,y);
int tmp=x;
x=y; y=tmp-(a/b)*y;
return;
}
int main()
{
scanf("%d%d",&n,&m); //n为逆元表达式中的a
int x=0,y=0;
exgcd(n,m,x,y);
x=(x%m+m)%m;
printf("%d\n",x);
return 0;
}
3.费马小定理求逆元
-
前提条件:当
为质数时才可使用 -
前置知识:费马小定理
若
是质数, 是正整数,且 不是 的倍数,则 -
已知
,那么由 可推出 ,所以 -
一般情况下,我们可以使用快速幂来求出
4.线性递推求逆元
-
当题目需要我们求出一串数字
的逆元时,我们会采用这种方式 -
我们记
的逆元为 ,已知 ,所以 -
设
,也就是说 是 的商, 是余数。那么就有:乘上
,就有: -
这样,我们就可以线性地递推出乘法逆元。但值得注意的是,一般题目中都要保证求出的逆元是正数,所以我们会在递推时往递推式中加一个
-
代码
inv[1]=1;
for(int i=2; i<=n; i++)
inv[i]=(long long)(m-m/i)*inv[m%i]%m;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】