[数论]乘法逆元
前言
今天去做某谷的乘法逆元模板,然后TLE,一看题解,发现自己十分的孤陋寡闻,只会exgcd的做法
于是博主决定写一篇乘法逆元的博客
定义
若\(a \times b \equiv 1 \pmod{b}\),且a,b互质,x为a在模b下的逆元,珂记为\(a^{-1}\)。
应用
把除法转换为乘法
方法
拓展欧几里得
线性同余方程\(a \times c \equiv 1 \pmod{b}\)中,\(c = 1\)的特殊情况,即求解\(a \times x + b \times 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 \times x \equiv 1 \pmod{p}\)
\(a \times 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} \rfloor \times 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\n"); inv[1] = 1;
for(int i = 2; i <= n; ++i)
inv[i] = p - (p / i) * inv[p % i] % p, printf("%lld\n", inv[i]);
return 0;
}