深入浅出乘法逆元

 1.模的运算律

 2.定义

 3.求解

  3.1费马小定理

  3.2扩展欧几里得算法

  3.3线性求解

深入浅出乘法逆元

模的运算律

先来一波模运算律表:

运算律 内容
交换律 \((a+b)\%p=(b+a)\%p\)
\((a\times b)\%p=(b\times a)\%p\)
结合律 \(((a+b)\%p+c)\%p=(a+(b+c)\%p)\%p\)
\(((a\times b)\%p\times c)\%p=(a\times (b\times c)\%p)\%p\)
分配率 \(((a+b)\%p\times c)\%p=((a\times c)\%p+(b\times c)\%p)\%p\)
\((a\times b)\%p=(a\%p\times b\%p)\%p\)
\((a+b)\%p=(a\%p+b\%p)\%p\)
\((a-b)\%p=(a\%p-b\%p)\%p\)

定义

有的时候我们需要对一个数取模,这很简单。但是在取模的过程中出现了除数,那么取模就没这么简单了:

\[\frac{7}{2}\%4=3\%4=3\]注意:\(\frac{7\%4}{2}=\frac{3}{2}=1\)是错误的

但万一是\(\frac{7^{10000}}{2}\%4\)计算机可无法先计算\(\frac{7^{10000}}{2}\)再\(\pmod4\),因为数字太大了。

这个时候我们就需要用到乘法逆元了,事实上:\(\frac{7^{10000}}{2}=(7*3)^{10000}\)。我们运用模的运算律可以通过边乘边取模即可得到答案,其中3是7在\(\pmod 4\)意义下的逆元。

关于逆元的严格定义如下:

\(若整数b,m互质,并且b\mid a,则存在整数x,使得a/b\equiv a*x\pmod m,则称x为b的模m乘法逆元,记为b^{-1}\pmod m\)

求解

3.1费马小定理

1

因为\(a/b\equiv a*b^{-1}\equiv a/b*b*b^{-1}\pmod m\),所以\(b*b^{-1}\equiv 1\pmod m\)2

如果m是质数(此时我们用符号\(p\)代替\(m\))并且\(b<p\),根据费马小定理\(b^{p-1}\equiv 1\pmod p\),即\(b*b^{p-2}\equiv1\pmod p\)。因此,当模数\(p\)为质数时,\(b^{p-2}\)为\(b\)的乘法逆元。

到最后我们可以用快速幂来迅速求出\(b^{p-2}\)。代码如下:

int ksm(int a,int b,int p) {
    int ans=1;
    for(; b; b>>=1,a=a*a%p)if(b&1)ans=ans*a%p;
    return ans;
}

时间复杂度是\(O(\log n)\)

3.2扩展欧几里得算法

扩展欧几里得算法的具体内容参考我写的:浅析扩展欧几里得算法(exgcd)

根据逆元的定义我们要求的是\(a*x\equiv1\pmod m\)关于x的同余方程,其中x为a在\(\pmod m\)意义下的逆元

事实上\[ax=by+1······①\]也就是\(ax\div m=y······1\)

变形①式得:\[ax-by=1\]

既然\(a,b\)都已知,就不难求出\(x和y\)了(但要注意\(y\)的系数\(-b\)必须是正整数,因为在计算机计算过程中如果模数是负的将导致结果出错)如果\(-b\)不是正整数,我们同时改变\(a,b\)的符号即可,\(a\)的符号并不影响结果。扩展欧几里得算法代码如下:

int exgcd(int a,int b,int &x,int &y) {
    if(b) {
        int c=exgcd(a,b,y,x);
        y-=a/b*x;
        return c;
    } else {
        x=1;
        y=0;
        return a;
    }
}

时间复杂度是\(O(\ln n)\)

3.3线性求解

当我们需要求解大量的逆元的时候,前两种的方法时间复杂度都要乘以\(n\),时间复杂度都不是很理想。所以我们就用\(O(n)\)的时间来快速求解。具体做法如下:假设我们要求x的逆元,那么:\[m=k*x+r\]\[k*x+r\equiv0\pmod m\]同乘以\(x^{-1}*r^{-1}\)得:\[k*r^{-1}+x^{-1}\equiv0\pmod m······①\]将②式变形得:\[x^{-1}\equiv-k*r^{-1}\pmod m\]

所以我们得到:\[x^{-1}=-\lfloor m/x\rfloor*(m\%x)^{-1}\]

那么只要建一个数组inv,初始值inv[1]=1。所以代码如下:

    for(int i=2; i<=n; i++)
        inv[i]=-(p/i)*inv[p%i];

  1. 这种方法的常数比较大。?
  2. \(b^{-1}\equiv b^{-1}\pmod m\)其中前一个是\(\div b\),后一个是\(a\)的逆元\(b\);根据模的运算律\((a/b*b*b^{-1})\%m=((a/b)\%m*((b*b^{-1})\%m)\%m\),显然\((b*b^{-1})\%m=1\)?

原文地址:https://www.cnblogs.com/kcfzyhq/p/8488243.html

时间: 2024-11-10 08:15:32

深入浅出乘法逆元的相关文章

HDU3037 Saving Beans(Lucas定理+乘法逆元)

题目大概问小于等于m个的物品放到n个地方有几种方法. 即解这个n元一次方程的非负整数解的个数$x_1+x_2+x_3+\dots+x_n=y$,其中0<=y<=m. 这个方程的非负整数解个数是个经典问题,可以+1转化正整数解的个数用插板法解决:$C_{y+n-1}^{n-1}=C_{y+n-1}^y$. 而0<=y<=m,最后的结果就是—— $$\sum_{i=0}^m C_{i+n-1}^i$$ $$C_{n-1}^0+C_{n}^1+C_{n+1}^2+\dots+C_{n-1

UVa 11174 (乘法逆元) Stand in a Line

题意: 有n个人排队,要求每个人不能排在自己父亲的前面(如果有的话),求所有的排队方案数模1e9+7的值. 分析: <训练指南>上分析得挺清楚的,把公式贴一下吧: 设f(i)为以i为根节点的子树的排列方法,s(i)表示以i为根的子树的节点总数. f(i) = f(c1)f(c2)...f(ck)×(s(i)-1)!/(s(c1)!s(c2)!...s(ck)!) 按照书上最开始举的例子,其实这个式子也不难理解,就是先给这些子树确定一下位置,即有重元素的全排列. 子树的位置确定好以后,然后再确定

LightOJ - 1050 (唯一分解+推公式+乘法逆元)

题意:求a^b的所有约数和对1e9+7取模的结果 思路:对于一个数p,进行唯一分解,则p=P1^M1*P2^M2*...*Pn^Mn,则p的所有约数之和等于(P1^0+P1^1+...+P1^M1)*(P2^0+P2^1+...+P2^M2)*...*(Pn^0+Pn^1+...+Pn^Mn), p^t=P1^(M1*t)*P2^(M2*t)*...*Pn^(Mn*t),每一个(Pn^0+Pn^1+...+Pn^Mn)利用等比数列可以直接推出公式为(Pn^(Mn*t+1)-1)/(Pn-1),用

【奇技淫巧】数学技巧之乘法逆元

一.写在前面 开始码这篇blog之前我就意识到,这篇blog将会是我到目前为止码出的所有blog中最水的一篇.说是讲乘法逆元,但蒟蒻博主自己都不会证明_(:з」∠)_所以只打算放一个说明书式的用法,还请诸位看官老爷轻喷. 二.关于乘法逆元 我们知道模法交配率(Magic Coitus Law)(←_←其实并没有这东西)并不适用于除法.用式子表示大概是这样的: 但乘法逆元(Multiplicative Inverse Modulo,下式中用a'表示)就可以完成这样一个奇妙的操作: 然后我们就能用模

乘法逆元...Orz

最近打的几场比赛,都出现了有关逆元的题目,今天就整理了一下... 求乘法逆元的几种方法:http://www.cnblogs.com/james47/p/3871782.html 博文转载链接:http://blog.csdn.net/acdreamers/article/details/8220787 今天我们来探讨逆元在ACM-ICPC竞赛中的应用,逆元是一个很重要的概念,必须学会使用它. 对于正整数和,如果有,那么把这个同余方程中的最小正整数解叫做模的逆元. 逆元一般用扩展欧几里得算法来求

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

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

乘法逆元(转)

定义:满足a*k≡1 (mod p)的k值就是a关于p的乘法逆元. 为什么要有乘法逆元呢? 当我们要求(a/b) mod p的值,且a很大,无法直接求得a/b的值时,我们就要用到乘法逆元. 我们可以通过求b关于p的乘法逆元k,将a乘上k再模p,即(a*k) mod p.其结果与(a/b) mod p等价. 证: 根据b*k≡1 (mod p)有b*k=p*x+1. k=(p*x+1)/b. 把k代入(a*k) mod p,得:(a*(p*x+1)/b) mod p               

乘法逆元及其应用

满足 a * k ≡ 1 (mod p) 的k 叫做 a关于p的乘法逆元.另一种表达方法是 k ≡ a-1 (mod p) 逆元在密码学中有广泛应用,AES密码体系的字节替代就是运用了逆元.(不知道说的smg) 应用: 我们知道(a+b)%p=(a%p+b%p)%p (a*b)%p=(a%p)*(b%p)%p 而求(a/b)%p时,可能会因为a是一个很大的数,不能直接算出来,却又不能(a/b)%p=(a%p/b%p)%p. 但是可以通过 k ≡ b-1 (mod p)  a / b = a *

loj #110. 乘法逆元

#110. 乘法逆元 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 这是一道模板题. 给定正整数 n nn 与 p pp,求 1∼n 1 \sim n1∼n 中的所有数在模 p pp 意义下的乘法逆元. 输入格式 一行两个正整数 n nn 与 p pp 输出格式 n nn 行,第 i ii 行一个正整数,表示 i ii 在模 p pp 意义下的乘法逆元. 样例 样例输入 10 13 样例输出