[数论]乘法逆元

前言

今天去做某谷的乘法逆元模板,然后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;
}
posted @ 2019-05-28 23:52  LinZhengmin  阅读(269)  评论(0编辑  收藏  举报

Contact with me