逆元——乘法逆元的应用
1、问题引入:
(1)对于m=(a/b)(mod p)问题,由于除法不能用同余定理,我们需要将除法转换成乘法
( a / b ) % p =a * inv ( b , p ) %p =( a%p * inv ( b , p )%p ) %p
(其中,inv ( b , p ) 为mod p意义下b的乘法逆元)
又或者:
(2)当我们要求(a/b) mod p的值,且a很大,大到会溢出;或者说b很大,大到会爆精度。无法直接求得a/b的值时,我们就要用到乘法逆元。
2、定义:
如果有ab≡1(modp),则称b是mod p意义下a的乘法逆元。记b=inv(a)或b=a^-1
3、性质:
每个数a均有唯一的与之对应的乘法逆元x,使得ax≡1(mod p) ,一个数有逆元的充分必要条件是gcd(a, p)=1,此时逆元唯一存在 。
模p意义下,1个数a如果有逆元x,那么除以a相当于乘以x。
4、逆元的求解
扩展欧几里得法:
#include<bits/stdc++.h>
using namespace std;
int exgcd(int a,int b,int &x,int &y)
{
if(b==0)
{
x=1,y=0;
return a;
}
int r = exgcd(b,a%b,x,y);
int t = x;
x = y;
y = t - a/b*y;
return r;
}
int inv(int n,int mod)///求n在模mod的情况下的逆元
{
int x,y;
int ans = exgcd(n,mod,x,y);
if(ans == 1)
return (x%mod+mod)%mod;
else
return -1;
}
int main()
{
int n,mod;
cin>>n>>mod;
int ans = inv(n,mod);
if(ans==-1)
cout<<"没有逆元"<<endl;
else
cout<<"逆元为:"<<ans<<endl;
return 0;
}
例题:hdu1576
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1576
原题:
要求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973)(我们给定的A必能被B整除,且gcd(B,9973) = 1)。
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int mod=9973;
int exgcd(int a,int b,int &x,int &y)
{
if(b==0)
{
x=1,y=0;
return a;
}
int r = exgcd(b,a%b,x,y);
int t = x;
x = y;
y = t - a/b*y;
return r;
}
int inv(int n,int mod)///求n在模mod的情况下的逆元
{
int x,y;
int ans = exgcd(n,mod,x,y);
if(ans == 1)
return (x%mod+mod)%mod;
else
return -1;
}
int main()
{
int t,b,n;
cin>>t;
while(t--)
{
cin>>n>>b;
int ans=inv(b,mod);
cout<<(n%mod*(ans%mod))%mod<<endl;
}
return 0;
}