乘法逆元的求法(5种)

Posted wuliking

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了乘法逆元的求法(5种)相关的知识,希望对你有一定的参考价值。

若a*b≡1(mod p)

即a,b互为mod p意义下的逆元

即(x/a)%p应为x*b%p

一、扩展欧几里得求逆元

根据a*b+p*k=1

板子O(logN):

技术图片
 1 #include<bits/stdc++.h>
 2 typedef long long ll;
 3 ll exgcd(ll a,ll b,ll &x,ll &y) {
 4     if(!b) {
 5         x=1,y=0;
 6         return a;
 7     }
 8     ll res=exgcd(b,a%b,y,x);
 9     y-=a/b*x;       ///x=x1,y=x1-a/b*y1   x1,y1代表下一状态
10     return res;
11 }
12 int main()
13 {
14     ll a,p,x,y;  ///扩展欧几里得计算a的逆元(mod p)
15     scanf("%lld%lld",&a,&p);
16     ll d=exgcd(a,p,x,y);
17     printf(d==1?"%lld":"-1",(x+p)%p);///最大公约数不为1,逆元不存在,输出-1
18     return 0;
19 }
View Code

二、费马小定理求逆元(p为素数)

p为素数,则有$a^{p-1}=1(mod p)$

则$a^{p-2}*a=1(mod p)$

即$a^{p-2}$为a mod p意义下的逆元

板子O(logp):

技术图片
 1 #include<bits/stdc++.h>
 2 typedef long long ll;
 3 ll quickpowmod(ll a,ll b,ll mod) {
 4     ll ans=1;
 5     while(b) {
 6         if(b&1) ans=(ans*a)%mod;
 7         b>>=1;
 8         a=(a*a)%mod;
 9     }
10     return ans;
11 }
12 int main()
13 {
14     ll a,p;  ///费马小定理计算a的逆元(mod p)
15     scanf("%lld%lld",&a,&p);
16     ll inva=quickpowmod(a,p-2,p);
17     printf("%lld",inva);
18     return 0;
19 }
View Code

 三、欧拉定理求逆元(a,p互素)

a,p互素,则有$a^{\varphi (p) }=1(mod p)$

则$a^{\varphi (p) -1}*a=1(mod p)$

即$a^{\varphi (p) -1}$为a mod p意义下的逆元

板子(logp):

技术图片
 1 #include<bits/stdc++.h>
 2 typedef long long ll;
 3 ll get_euler(ll x) {
 4     ll ans=x;
 5     for(ll i=2;i*i<=x;i++)
 6         if(x%i==0) {
 7             ans=ans/i*(i-1);
 8             while(ans%i==0) ans/=i;
 9         }
10     if(ans>1) ans=ans/x*(x-1);
11     return ans;
12 }
13 ll quickpowmod(ll a,ll b,ll mod) {
14     ll ans=1;
15     while(b) {
16         if(b&1) ans=(ans*a)%mod;
17         b>>=1;
18         a=a*a%mod;
19     }
20     return ans;
21 }
22 int main()
23 {
24     ll a,p,x,y;
25     scanf("%lld%lld",&a,&p);    ///a与p互素
26     ll inva=quickpowmod(a,get_euler(p)-1,p);
27     printf("%lld",inva);
28     return 0;
29 }
View Code

 四、递推求逆元

设p是模数,i是待求的逆元,我们求的是$i^{-1}$在mod p意义下的值

$p=k * i + r $,令 r < i,则k=p/i,r=p%i 

$k * i + r ≡0 (mod p)$

$k * r^{-1} + i^{-1} ≡0 (mod p)$

$ i^{-1} ≡ - k * r^{-1} (mod p)$

$ i^{-1} ≡ - \frac {p} {i} * inv( p mod i )  (mod p) $

技术图片
1 LL inv[mod+5];
2 void getInv(LL mod)
3 {
4     inv[1]=1;
5     for(int i=2;i<mod;i++)
6         inv[i]=(mod-mod/i)*inv[mod%i]%mod;
7 }
View Code
  •  适用范围:mod数是不大的素数而且多次调用,比如卢卡斯定理。

五、递归求逆元

技术图片
1 LL get_inv(int i) {
2     if(i==1) return 1;
3     return (mod-mod/i)*(inv[mod%i])%mod;
4 }
View Code

 

参考博客:https://blog.csdn.net/xiaoming_p/article/details/79644386

 

以上是关于乘法逆元的求法(5种)的主要内容,如果未能解决你的问题,请参考以下文章

逆元的求法

乘法逆元简单说说乘法逆元的求法

7的逆元怎么算

数论笔记-同余

【总结】逆元的求法

求乘法逆元的几种姿势