推荐博客:https://blog.csdn.net/baidu_35643793/article/details/75268911
1.费马小定理
在是素数的情况下,对任意整数都有。
如果无法被整除,则有可以在为素数的情况下求出一个数的逆元,即为逆元。
题目中的数据范围1<=x<=10^9,p=1000000007,p是素数;
所以x肯定就无法被p整除啊,所以最后就得出x的(p-2)次方为x的逆元。
时间复杂度为O(logn);
代码:
typedef long long ll;
const int mod=1e9+7;
ll qpow(ll a,ll b)
{
if(b<0) return 0;
ll ans=1;
a%=mod;
while(b)
{
if(b&1) ans=(ans*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return ans;
}
ll inv(ll a)
{
return qpow(a,mod-2);
}
2.扩展欧几里得
代码:
ll extend_gcd(ll a, ll b, ll x, ll y) {
if (b == 0) {
x = 1, y = 0;
return a;
}
else {
ll r = extend_gcd(b, a % b, y, x);
y -= x * (a / b);
return r;
}
}
ll inv(ll a, ll n) {
ll x, y;
extend_gcd(a, n, x, y);
x = (x % n + n) % n;
return x;
}
(3) 逆元线性筛 ( P为质数 )
求1,2,...,N关于P的逆元(P为质数)
扫描二维码关注公众号,回复:
8992909 查看本文章
复杂度:O(N)
代码:
const int mod = 1e9+7;
const int maxn = 10005;
int inv[maxn];
inv[1] = 1;
for(int i = 2; i < 10000; i++)
inv[i] = inv[mod % i] * (mod - mod / i) % mod;
如果是求阶乘的逆元呢?(阶乘数组:fac[ ])
fac[0]=1;
for(ll i=1;i<=maxn;i++)
fac[i]=(fac[i-1]*i)%mod;
inv[maxn]=mod_pow(fac[maxn],mod-2);
for(ll i=maxn-1;i>=0;i--)
inv[i]=(inv[i+1]*(i+1))%mod;