前言
今天去做某谷的乘法逆元模板,然后TLE,一看题解,发现自己十分的孤陋寡闻,只会exgcd的做法
于是博主决定写一篇乘法逆元的博客
定义
若(a imes b equiv 1 pmod{b}),且a,b互质,x为a在模b下的逆元,珂记为(a^{-1})。
应用
把除法转换为乘法
方法
拓展欧几里得
线性同余方程(a imes c equiv 1 pmod{b})中,(c = 1)的特殊情况,即求解(a imes x + b imes y = 1)。
那么代码如下
#include <cstdio>
#define ll long long
void exgcd(ll a, ll b, ll &x, ll &y){
if (!b)
x = 1, y = 0;
else
exgcd(b, a % b, y, x), y -= a / b * x;
}
int main(){
ll n, p; scanf("%lld %lld", &n, &p); ll x, y;
exgcd(n, p, x, y);
x = (x % p + p) % p;
printf("%lld", x);
return 0;
}
快速幂
使用费马小定理
费马小定理 若p为素数,a为正整数,且a、p互质。 则有(a^{p-1} equiv 1 pmod{p})
求逆元公式:
(x equiv a^{p-2} pmod{p})
求逆元公式推导:
(a imes x equiv 1 pmod{p})
(a imes x equiv a^{p-1} pmod{p})
(x equiv a^{p-2} pmod{p})
那么代码如下:
#include <cstdio>
#define ll long long
ll pow(ll a, ll b, ll mod){
a %= mod; ll ans = 1;
for (; b; b >>= 1, a = (a * a) % mod)
if(b & 1) ans = (ans * a) % mod;
return ans;
}
int main(){
ll a, p; scanf("%lld %lld", &a, &p);
ll x = pow(a, p - 2, p);
printf("%lld", x);
return 0;
}
递推
证明代填
公式 (inv[i] = p - lfloor frac{p}{i}
floor imes inv[p ; mod ; i] ; mod ; p)
那么代码如下:
#include<cstdio>
#define ll long long
ll inv[3000005];
int main(){
int n, p; scanf("%d %d", &n, &p);
printf("1
"); inv[1] = 1;
for(int i = 2; i <= n; ++i)
inv[i] = p - (p / i) * inv[p % i] % p, printf("%lld
", inv[i]);
return 0;
}