乘法逆元
SuperMarxet · · 个人记录
在实数范围内,当
在mod P意义下,我们同样想要这么一个的东西使
“
为什么我们需要逆元呢?
首先,在计算当中,我们可能需要计算形如“
或者,当我们计算模意义下的除法的时候,我们通常需要边做边模,这样比较省空间,可以有效防止爆范围,这个时候我们也需要使用逆元来把除法转换成乘法。
总之逆元非常的好用,但是怎么去求呢?
首先我们要知道一个定理:裴蜀定理:
对于整数a,b,设他们的最大公约数
所以有
这个时候可以发现,只要令
代码实现:
#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
using namespace std;
ll a,p;
void exgcd(ll a,ll b,ll &x,ll &y){
if(b==0){
x=1,y=0;
return;
}
exgcd(b,a%b,y,x);
y-=a/b*x;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int n;
cin>>a>>p;
ll x,y;
exgcd(a,p,x,y);
x=(x%p+p)%p;
cout<<x<<endl;
return 0;
}
这样我们得出的x就是a在模P意义上的逆元。
或者,如果我们不想用扩欧,也有另一种方法来做。
费马小定理,指的是如果p是一个质数而整数a不是p的倍数,则有
那通过这个定理我们就能知道,
所以
代码实现:
#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
using namespace std;
const int mod=19260817;
string s,t;
ll a,b;
ll fpow(ll x,ll y){
ll t=1;
while(y){
if(y&1) t=t*x%mod;
x=x*x%mod;
y>>=1;
}
return t;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>s>>t;
for(int i=0;i<s.size();i++) a=(a*10+s[i]-'0')%mod;
for(int i=0;i<t.size();i++) b=(b*10+t[i]-'0')%mod;
if(a%mod&&!(b%mod)) cout<<"Angry!";
cout<<a*fpow(b,mod-2)%mod;
return 0;
}
这样我们就算出了a在模P意义上的逆元。但是现在问题又来了:怎么证明在0到p的范围内模P的逆元是唯一的?
我们假设