乘法逆元求法

Posted handwer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了乘法逆元求法相关的知识,希望对你有一定的参考价值。

原创建时间:2018-08-05 08:24:19

数论中的重要内容

注意:本文只讨论模数为质数的情况,因为当模数为合数时,不一定所有数都有逆元

定义

(mod p)的意义下,我们把(x)的乘法逆元写作(x^{-1})。乘法逆元有这样一条性质:

[x imes x^{-1} equiv 1 (mod p)]

乘法逆元有什么用呢?

模意义下的除法运算

除法运算对于模运算来说并不是「封闭」的,所以我们可以把除法转化成乘法

费马小定理求法

前置知识:「快速幂」

(a^{p-1} equiv 1 (mod p)%)

经过变形,可得

(a imes a^{p-2} equiv 1(mod p))

由定义可得,(a)的乘法逆元就是(a^{p-2})

这就要用到「快速幂」

inline int slowPower(int a, int b, int p) {
    int ans = 1;
    while (b) {
        if (b & 1) ans = 1ll * ans * a % p;
        a = 1ll * a * a % p;
        b >>= 1;
    }
    return ans;
}

inline int invMod(int x, int p) {
    return slowPower(x, p - 2, p);
}

代码实现

输出1到n的逆元

/* -- Basic Headers -- */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>

/* -- STL Iterators -- */
#include <vector>
#include <string>
#include <stack>
#include <queue>

/* -- External Headers -- */
#include <map>
#include <cmath>

/* -- Defined Functions -- */
#define For(a,x,y) for (int a = x; a <= y; ++a)
#define Forw(a,x,y) for (int a = x; a < y; ++a)
#define Bak(a,y,x) for (int a = y; a >= x; --a)

namespace FastIO {
    inline long long int getint() {
        long long int s = 0, x = 1;
        char ch = getchar();
        while (!isdigit(ch)) {
            if (ch == '-') x = -1;
            ch = getchar();
        }
        while (isdigit(ch)) {
            s = s * 10ll + ch - '0';
            ch = getchar();
        }
        return s * x;
    }
    inline void __basic_putint(long long int x) {
        if (x < 0) {
            x = -x;
            putchar('-');
        }
        if (x >= 10) __basic_putint(x / 10);
        putchar(x % 10 + '0');
    }
    
    inline void putint(long long int x, char external) {
        __basic_putint(x);
        putchar(external);
    }
}


namespace Solution {
    const int MAXN = 5000000 + 10;
    
    long long int n, k, HA, a[MAXN];
    long long int fac[MAXN], invf[MAXN];
    
    long long int SlowPower(long long int a, long long int x) {
        //  a^x mod m
        long long int ret = 1;
        if (x == 1) return a;
        while (x) {
            if (x & 1) ret = ret * a % HA;
            a = a * a % HA;
            x >>= 1;
        }
        return ret;
    }
}

signed main() {
    using namespace Solution;
    using namespace FastIO;
    n = getint(); HA = getint();
    fac[0] = 1;
    for (int i = 1; i <= n; ++i) {
        fac[i] = (fac[i - 1] * i) % HA;
    }
    invf[n] = SlowPower(fac[n], HA - 2);
    for (long long int i = n - 1; i >= 1; --i) {
        invf[i] = (invf[i + 1] * (i + 1)) % HA;
    }
    for (long long int i = 1; i <= n; ++i) {
        printf("%lld
", (invf[i] * fac[i - 1]) % HA);
    }
    return 0;
}

以上是关于乘法逆元求法的主要内容,如果未能解决你的问题,请参考以下文章

乘法逆元的求法(5种)

HDU 1576 -- A/B (总结乘法逆元的几种求法)

逆元的求法

乘法逆元模板

乘法逆元学习笔记

乘法逆元(updating)