概述
对于一个模方程
ax≡1(mod
m)
,x就是a的乘法逆元,记作
a−1
。
那么求
a/b
mod
m
的时候,求
ps:和模方程一样,当(a,m)|1(即(a,m)=1)的时候存在解,否则无解。
方法1
用扩展欧几里得算法即可求得x。
int exgcd(int a,int b,int &x,int &y)
{
if (!b) {x=1;y=0;return a;}
int r=exgcd(b,a%b,x,y),t=x;x=y;y=t-a/b*y;
return r;
}
int mul_INV(int a,int m)
{
int x,y;if (exgcd(a,m,x,y)!=1) return -1;
return (x%m+m)%m;
}
方法2
一种递推的算法,可以
O(p)
推出1~p-1的逆元(算出INV[i]的前提是INV[i]存在),由于>p的逆元可以回到1~p-1,所以不用求。
首先
1−1≡1(mod
p)
,设
p=a∗i+r
,则
a=⌊p/i⌋
,
r=p
mod
i
,放到mod p的意义下:
同乘
i−1
,
r−1
,得:
a∗(r−1+i−1≡0(mod
p)
i−1≡−a∗r−1(mod
p)
i−1≡−⌊p/i⌋∗(p
mod
i)(mod
p)
所以说INV[i]=-(p/i)*INV[p%i]
。
方法3
根据费马小定理,当p为素数,a为正整数, gcd(a,p)=1 时, ap−1≡1(mod p) ,所以 ap−2∗a≡1(mod p) ,则 ap−2 mod m <script type="math/tex" id="MathJax-Element-44">m</script>就是a的逆元。
模板
HDU1576,求A/B%MOD。
#include<cstdio>
using namespace std;
const int MOD=9973;
int te,A,B;
int exgcd(int a,int b,int &x,int &y)
{
if (!b) {x=1;y=0;return a;}
int r=exgcd(b,a%b,x,y),t=x;x=y;y=t-a/b*y;
return r;
}
int mul_INV(int a,int m)
{
int x,y;if (exgcd(a,m,x,y)!=1) return -1;
return (x%m+m)%m;
}
int main()
{
freopen("mul_INV.in","r",stdin);
freopen("mul_INV.out","w",stdout);
scanf("%d",&te);
for (int i=1;i<=te;i++)
{
scanf("%d%d",&A,&B);
printf("%d\n",A*mul_INV(B,MOD)%MOD);
}
return 0;
}