求逆元的史上最好方法总结
简单的来说,已知a和m,求a的逆元(如果存在的话等于1/a mod m)。
现分几种情况讨论。
1. m是素数(a<m)。
a的逆元必然存在。两种方法求逆元,在线用拓展欧几里得算,打表用递推。
不用费马小定理在线算逆元是因为拓展欧几里得复杂度O(logn),费马小定理复杂度O(log mod),后者比前者慢一些。
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define scan(i) scanf("%d",&i) 4 #define f(i,a,b) for(int i=a;i<=b;i++) 5 #define pf printf 6 using namespace std; 7 ll exgcd(ll a,ll b,ll &x,ll &y)//扩展欧几里得算法 8 { 9 if(b==0) 10 { 11 x=1,y=0; 12 return a; 13 } 14 ll ret=exgcd(b,a%b,y,x); 15 y-=a/b*x; 16 return ret; 17 } 18 ll getinv(int a,int mod)//求a在mod下的逆元,不存在逆元返回-1 19 { 20 ll x,y; 21 ll d=exgcd(a,mod,x,y); 22 return d==1?(x%mod+mod)%mod:-1; 23 } 24 int main(){ 25 cout<<getinv(3,7); 26 return 0; 27 }
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define scan(i) scanf("%d",&i) 4 #define f(i,a,b) for(int i=a;i<=b;i++) 5 #define pf printf 6 using namespace std; 7 const int M=10000; 8 ll inv[M+5]; 9 void getInv(ll mod)//离线打表求逆元 10 { 11 inv[1]=1; 12 for(int i=2;i<mod;i++) 13 inv[i]=(mod-mod/i)*inv[mod%i]%mod; 14 } 15 int main(){ 16 getInv(7); 17 cout<<inv[3]; 18 return 0; 19 }
2. m不是素数
当gcd(a,m)!=1时,a的逆元不存在。其他情况下,打表就不行了,只能在线算了。具体方法是用上面的拓展欧几里得求,复杂度O(logn),下面贴个费马小定理的板子吧~~
ll qkpow(ll a,ll p,ll mod) { ll t=1,tt=a%mod; while(p) { if(p&1)t=t*tt%mod; tt=tt*tt%mod; p>>=1; } return t; } ll getInv(ll a,ll mod) { return qkpow(a,mod-2,mod);//这里本来该放的是欧拉函数,可以详见本人的其他博客~ }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!