介绍:如果,且gcd(x,y)=1,(a与p互质),则称a关于模p的乘法逆元为x。
乘法逆元可解决(b/a)%p的问题。
由同余定理知
a*b%m=( (a%m) * (b%m) )%m
则有 a*x*(b/a)%m=( (a*x%m) * ((b/a)%m) )%m=(b/a)%m (x是a的逆元所以a*x%m=1)
故 a*x*(b/a)%m=x*b%m=(b/a)%m
所以原式子等于分子乘以分母的逆元再对m取模。
1.拓展欧几里得算法求逆元
等价于ax-py=1,可写为ax+by=1.于是问题等价于求一组x0,y0,并验证GCD(a,b)=1 。可用拓展欧几里得算法解决。
typedef long long ll;
int Extended_GCD(int a,int b,int &x,int &y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
int gcd=Extened_GCD(b,a%b,x,y);
int temp=x;
x=y;
y=temp-a/b*y;
return gcd;
}
int inv(int a,int mod)
{
ll x,y;
ll d=Extended_GCD(a,mod,x,y);//判断a,b是否互质,即gcd(a,b)=1
return d==1?(x%mod+mod)%mod:-1;
}
2.费马小定理求逆元
费马小定理:若,则
,即
。
所以a的逆元就是,可用快速幂算法求出。
typedef long long ll;
ll mod_pow(ll x,ll n,ll mod)
{
int res=1;
while(n)
{
if(n&1)
res=(res*x)%mod;
x=x*x%mod;
n>>=1;
}
return res;
}
ll inv(ll a,ll mod)
{
return mod_pow(a,mod-2,mod);
}