乘法逆元求法

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

数论中的重要内容

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

定义

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

\[x \times x^{-1} \equiv 1\ (\bmod\ p)\]

乘法逆元有什么用呢?

模意义下的除法运算

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

费马小定理求法

前置知识:「快速幂」

\(a^{p-1} \equiv 1 (\bmod\ p)%\)

经过变形,可得

\(a \times a^{p-2} \equiv 1(\bmod\ 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\n", (invf[i] * fac[i - 1]) % HA);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/handwer/p/11745355.html

时间: 2024-10-10 11:16:12

乘法逆元求法的相关文章

乘法逆元及求法

在开始之前我们先介绍3个定理: 1.乘法逆元(在维基百科中也叫倒数,当然是 mod p后的,其实就是倒数不是吗?): 如果ax≡1 (mod p),且gcd(a,p)=1(a与p互质),则称a关于模p的乘法逆元为x. 2.费马小定理(定义来自维基百科): 假如a是一个整数,p是一个质数,那么是p的倍数,可以表示为 如果a不是p的倍数,这个定理也可以写成 3. 扩展欧几里得 (定义来自维基百科): 已知整数a.b,扩展欧几里得算法可以在求得a.b的最大公约数的同时,能找到整数x.y(其中一个很可能

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

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1576 A/B Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 7264    Accepted Submission(s): 5774 Problem Description 要求(A/B)%9973,但由于A很大,我们只给出n(n=A%99

Codeforces 543D Road Improvement(树形DP+乘法逆元)

题目大概说给一棵树,树的边一开始都是损坏的,要修复一些边,修复完后要满足各个点到根的路径上最多只有一条坏的边,现在以各个点为根分别求出修复边的方案数,其结果模1000000007. 不难联想到这题和HDU2196是一种类型的树形DP,因为它们都要分别求各个点的答案.然后解法也不难想: dp0[u]表示只考虑以u结点为根的子树的方案数 dp1[u]表示u结点往上走,倒过来,以它父亲为根那部分的方案数 有了这两部分的结果,对于各个点u的答案就是dp0[u]*(dp1[u]+1).这两部分求法如下,画

乘法逆元

定义:当(a,p)=1时,存在ax≡1(mod p),则x叫作a在模p意义下的乘法逆元. 求法: 1.当p为质数时,由费马小定理,得ap-1≡1(mod p),即(a·ap-2)≡1(mod p),则a在模p意义下的乘法逆元是ap-2,直接用快速幂可求得. 2.当p不为质数时,用扩展欧几里得算法求a的逆元. 代码: 1 int exgcd(int a,int b,int &x, int &y) 2 { 3 int d=a; 4 if(b!=0){ 5 d=exgcd(b,a%b,y,x);

求乘法逆元的几种方法

(数学渣,下面的文字可能有误,欢迎指教)乘法逆元的定义貌似是基于群给出的,比较简单地理解,可以说是倒数的概念的推广.记a的关于模p的逆元为a^-1,则a^-1满足aa^-1≡ 1(mod p) 加减乘与模运算的顺序交换不会影响结果,但是除法不行.有的题目要求结果mod一个大质数,如果原本的结果中有除法,比如除以a,那就可以乘以a的逆元替代. 在mod p的运算中,a存在乘法逆元当且仅当a与p互质.一般题目给的是一个大质数,所以只要a不是p的倍数,就以求乘法逆元. 目前了解到的求法有三种:1.扩展

BZOJ_[HNOI2008]_Cards_(置换+Burnside引理+乘法逆元+费马小定理+快速幂)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1004 共n个卡片,染成r,b,g三种颜色,每种颜色的个数有规定.给出一些置换,可以由置换得到的染色方案视为等价的,求等价类计数. 分析 给出置换求等价类计数,用Burnside引理:等价类计数=(每一个置换不动点的和)/置换数.(不知道的建议去看白书) 其中不动点是指一个染色方案经过置换以后染色与之前完全相同. 1.求不动点个数. 不动点的话同一个循环内的每一个点的颜色必须相同(否则不同颜色

关于乘法逆元的世界

引子 经过几天的努力,终于将逆元这个大难题给攻克了--心情激动的一时无法平复.下面就简单介绍一下关于逆元的知识,来记录自己的成果,也希望能够帮助到别人.某些地方可能理解的不够深入,还请多多包涵. 定义 逆元,又称数论倒数,如果a*x≡1 (mod p),且gcd(a,p)=1(a与p互质),则称a关于模p的乘法逆元为x.(来自维基百科) 怎么说呢,逆元其实就是一个相当于倒数的东西,只不过是多模了一个p而已.要说它有什么用,那么请回忆一下倒数有什么用吧.没错,在上小学时,老师就教导过我们,除以一个

[模板]乘法逆元

本博客所有代码基于题目 luogu_P3811 逆元: 一般用于求 (a/b) mod p  定义: 若 a*x ≡ 1 (mod p) ,且 a 与 p 互质,那么我们就能定义: x 为 a 的逆元,记为 a^-1 ,所以我们也可以称 x 为 a 的倒数(mod p意义下). 所以对于 (a/b) mod p ,我们就可以求出 b 在 mod p 意义下的逆元,然后乘上 a ,再 mod p ,就是这个乘法逆元的值了. 求法: First:费马小定理 定理内容:如果 a , p 互质,那么 a

数论入门2——gcd,lcm,exGCD,欧拉定理,乘法逆元,(ex)CRT,(ex)BSGS,(ex)Lucas,原根,Miller-Rabin,Pollard-Rho

数论入门2 另一种类型的数论... GCD,LCM 定义\(gcd(a,b)\)为a和b的最大公约数,\(lcm(a,b)\)为a和b的最小公倍数,则有: 将a和b分解质因数为\(a=p1^{a1}p2^{a2}p3^{a3}...pn^{an},b=p1^{b1}p2^{b2}p3^{b3}...pn^{bn}\),那么\(gcd(a,b)=\prod_{i=1}^{n}pi^{min(ai,bi)},lcm(a,b)=\prod_{i=1}^{n}pi^{max(ai,bi)}\)(0和任何