扩展欧几里得求逆元
ax=1(mod p),a,p互质,那么原式可以写成ax+py=gcd(a,p)(mod p),a,p互质,所以gcd(a,p)=1,所以原式等于ax+py=1(mod p)
,直接通过扩展欧几里得算法即可轻松求得,如果不知道什么是扩展欧几里得算法,建议先学一下https://blog.csdn.net/TheWayForDream/article/details/109014990
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll quik_pow(ll dishu , ll zhishu, ll mod)
{
ll ans=1;
while(zhishu)
{
if(zhishu&1)
{
zhishu--;
ans=ans*dishu%mod;
}
else
{
zhishu>>=1;
dishu=dishu*dishu%mod;
}
}
return ans;
}
ll exgcd(ll &x,ll &y,ll &g,ll a,ll b)//g为gcd(a,b)
{
if(b==0)
{
x=1;
y=0;
g=a;
return 0;
}
exgcd(x,y,g,b,a%b);
ll x1=y;
ll y1=x-(a/b)*y;
x=x1;
y=y1;
return 0;
}
int main()
{
ll a,b;
cin>>a>>b;
ll x,y,g;
exgcd(x,y,g,a,b);
ll s=b/g;
x=(x%s+s)%s;//a的逆元,这里是避免x出现负数
cout<<x;
return 0;
}
通过费马小定理求逆元
什么是费马小定理
定义:如果p是素数,那么a^(p-1)=1(mod p) ,所以我们令ax=1(mod p),那么x=a^(p-2),这里的x就是a逆元,直接用快速幂求得即可
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll quik_pow(ll dishu , ll zhishu, ll mod)
{
ll ans=1;
while(zhishu)
{
if(zhishu&1)
{
zhishu--;
ans=ans*dishu%mod;
}
else
{
zhishu>>=1;
dishu=dishu*dishu%mod;
}
}
return ans;
}
int main()
{
cin>>a>>p;
ll ans=quik_pow(a,p-2,p);
}
线性求逆元
当题目要求你求某段区间的所有关于模p的逆元的时候,这个算法是非常快的
学习中,待完善,还请见谅