逆元:
对于正整数a和m,如果ax≡1(mod m),(即ax%m=1),那么把这个同余方程中x的最小正整数解叫做 a模m的逆元。
一个数有逆元的充分必要条件是gcd(a,m)=1,此时逆元唯一存在
除法取模
a/b mod m等价于a*b’mod m (b’是b模m的逆元)
下面是几种求逆元的方法
1.扩展欧几里得
代码如下
#include<stdio.h>
#define ll long long
ll exgcd(ll b,ll m,ll& x,ll& y){
if(!m){
x=1;
y=0;
return x;
}
else{
exgcd(m,b%m,y,x);
y-=x*(b/m);
}
return x;
}
int main(){
ll b,m,x,y;
while(scanf("%lld%lld",&b,&m)!=EOF){ //b有逆元的前提gcd(b,m)=1
x=exgcd(b,m,x,y);
x=(x%m+m)%m;
printf("%lld\n",x);//x即为b的逆元b'
}
return 0;
}
2.费马小定理
在模m为素数的条件下有 b^(m-1)=1(mod m);
则 b模m的逆元b’ =b^(m-2)
用快速幂求即可。
代码如下
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<cmath>
#include<string>
#define LL long long
using namespace std;
LL b,m;
LL pow(LL x,LL n){
LL res=1;
while(n>0){
if(n&1)
res=(res*x);
x=(x*x);
n>>=1;
}
return res;
}
int main()
{
while(cin>>b>>m){
cout<<pow(b,m-2)%m<<endl;
}
return 0;
}
3.求逆元的一般公式
a/b mod m=a mod (m*b) /b
注意:实际上a mod (m*b)/b这种的对于所有的都适用,不区分互不互素,而费马小定理和扩展欧几里得算法求逆元是有局限性的,它们都会要求与互素,如果a与m不互素,那就没有逆元,这个时候需要a mod (bm)/b来搞(此时就不是逆元的概念了)。但是当a与m互素的时候,bm可能会很大,不适合套这个一般公式,所以大部分时候还是用逆元来搞.