求逆元、阶乘逆元、线性求逆元

2024-04-03 07:38
文章标签 线性 阶乘 逆元

本文主要是介绍求逆元、阶乘逆元、线性求逆元,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • 什么是逆元
  • 如何求逆元
  • 阶乘逆元
  • 线性求逆元

本文章内,若无特殊说明,数字指的是整数,除法指的是整除。

什么是逆元

我们称\(a\)\(b\)在模\(p\)情况下的逆元,则有\(a \times b \equiv 1 ( mod\,\,p)\)
所以呢,我们其实可以将逆元看成一个数的相反数。所以在除以一个数的时候,就相当于乘上它的相反数。

如何求逆元

我们先来看看什么情况下有逆元。

当且仅当\(gcd(b,p)=1\)时,\(b\)在模\(p\)情况下有逆元。

这个结论可由裴蜀定理显然推得,下面一段来自百度百科,若读者对证明有兴趣,可以自行了解。

裴蜀定理(或贝祖定理,Bézout's identity)得名于法国数学家艾蒂安·裴蜀,说明了对任何整数\(a\)\(b\)和它们的最大公约数\(d\),关于未知数\(x\)\(y\)的线性不定方程(称为裴蜀等式):若\(a\),\(b\)是整数,且\((a,b)=d\),那么对于任意的整数\(x\),\(y\),\(ax+by\)都一定是\(d\)的倍数,特别地,一定存在整数\(x\),\(y\),使\(ax+by=d\)成立。

拓展欧几里得求逆元

下面介绍如何用拓展欧几里得求逆元。

我们求\(b\)在模\(g\)意义下的逆元,根据\(a \times b \equiv 1 ( mod\,\,p)\),得到\(a\times b + k\times p = 1\)
我们知道,\(gcd(b,p)=gcd(p,b \% p)\),所以\(a'\times p+k'\times (b \% p)=1\)同样有解。而由于\(gcd(b,p)=1\),辗转相除法时,总有\(a''\times 1 + k'' \times 0 = 1\)
此时我们不妨令\(a''=1,k''=0\)
现在我们考虑怎么推回去。
\[ a'\times p+k'\times (b \% p)=1 \]

\[ \Rightarrow a'\times p+k'\times( b-\left \lfloor \frac{b}{p} \right \rfloor \times p)=1 \]

\[ \Rightarrow k'\times b+(a'-\left \lfloor \frac{b}{p} \right \rfloor \times k') \times p=1 \]

\(a\times b + k\times p = 1\)对照,得到\(a=k',\,\,\,k=a'- \left \lfloor \frac{b}{p} \right \rfloor\times k'\)。那么这样,我们就得到了\(a\times b + k\times p = 1\)的一组解,同时,\(a\)就是\(b\)在模\(p\)下的逆元。
附C++程序

#include <bits/stdc++.h>
using namespace std;
void ExPower( int b, int p, int & a, int & k ) {if( p == 0 ) {a = 1; k = 0;return;}ExPower( p, b % p, k, a );k -= b / p * a;return;
}
int main() {int b, p;cin >> b >> p;int a, k;ExPower( b, p, a, k );if( a < 0 ) a += p;cout << a << endl;return 0;
}
费马小定理求逆元

我们知道,当\(p\)为素数,并且\(gcd(a,p)=1\)时,我们有\(a^{p-1} \equiv 1 (mod\,\,p)\)。那么我们就有\(a^{p-2}\times a \equiv 1(mod \,\, p)\)。所以逆元就是\(a^{p-2}\)了。

阶乘逆元

如果我们需要求\(0!\)\(n!\)的逆元,对于每个元素都求一遍,就显得有点慢。(虽然\(exPower\)的时间快到可以认为是小常数。)
前面我们说了,逆元就可一看做是求倒数。那么不就有\(\frac{1}{(n+1)!}\times (n+1)=\frac{1}{n!}\)
附C++程序:

int inv( int b, int p ) {int a, k;exPower( b, p, a, k );if( a < 0 ) a += p;return a;
}
void init( int n ) {Fact[ 0 ] = 1;for( int i = 1; i <= n; ++i ) Fact[ i ] = Fact[ i - 1 ] * i % Mod;INV[ n ] = inv( Fact[ n ], Mod );for( int i = n - 1; i >= 0; --i ) INV[ i ] = INV[ i + 1 ] * ( i + 1 ) % Mod;return;
}

线性求逆元

按照上面的方法,如果我们要求\(1\)\(p-1\)关于\(p\)的逆元,而\(p\)较大时,时间复杂度有点吃不消。而我们有一种更强的做法,可以在\(O(p)\)的时间内解决。

对于当前的\(i\),我们设\(p=k\times i+r\)。于是:
\[ \begin{aligned} k \times i + r & \equiv 0 &\,\,(mod \,\, p) \\ k \times i \times ( i^{-1} \times r ^{-1}) + r \times (i^{-1} \times r^{-1}) &\equiv 0 &\,\,( mod \,\, p) \\ k \times r^{-1} + i ^ {-1} & \equiv 0 &\,\, (mod \,\, p)\\ i^{-1} & \equiv -k \times r^{-1} &\,\, (mod \,\, p) \\ i^{-1} & \equiv - \left \lfloor \frac{p}{i}\right \rfloor \times r^{-1} &\,\,(mod\,\,p) \end{aligned} \]
所以代码就大致如下:

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

转载于:https://www.cnblogs.com/chy-2003/p/9656801.html

这篇关于求逆元、阶乘逆元、线性求逆元的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/872299

相关文章

Python实现阶乘的四种写法

《Python实现阶乘的四种写法》本文主要介绍了Python实现阶乘的六种写法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录第一种:推导式+循环遍历列表内每个元素相乘第二种:调用functools模块reduce的php累计

hdu4828(卡特兰数+逆元)

这题的前几个数据分别为1,2,5,14,32......................然后确定这是个卡特兰数列 下面来介绍下卡特兰数,它的递推式为f[i+1] = f[i]*(4*n - 6)/n,其中f[2] = f[3] =1;f[4] = 2;f[5] = 14;f[6] = 32.................................. 但是这题的n太大了,所以要用到逆元,

hdu4869(逆元+求组合数)

//输入n,m,n表示翻牌的次数,m表示牌的数目,求经过n次操作后共有几种状态#include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdlib.h>#includ

uva 10061 How many zero's and how many digits ?(不同进制阶乘末尾几个0)+poj 1401

题意是求在base进制下的 n!的结果有几位数,末尾有几个0。 想起刚开始的时候做的一道10进制下的n阶乘末尾有几个零,以及之前有做过的一道n阶乘的位数。 当时都是在10进制下的。 10进制下的做法是: 1. n阶位数:直接 lg(n!)就是得数的位数。 2. n阶末尾0的个数:由于2 * 5 将会在得数中以0的形式存在,所以计算2或者计算5,由于因子中出现5必然出现2,所以直接一

线性因子模型 - 独立分量分析(ICA)篇

序言 线性因子模型是数据分析与机器学习中的一类重要模型,它们通过引入潜变量( latent variables \text{latent variables} latent variables)来更好地表征数据。其中,独立分量分析( ICA \text{ICA} ICA)作为线性因子模型的一种,以其独特的视角和广泛的应用领域而备受关注。 ICA \text{ICA} ICA旨在将观察到的复杂信号

✨机器学习笔记(二)—— 线性回归、代价函数、梯度下降

1️⃣线性回归(linear regression) f w , b ( x ) = w x + b f_{w,b}(x) = wx + b fw,b​(x)=wx+b 🎈A linear regression model predicting house prices: 如图是机器学习通过监督学习运用线性回归模型来预测房价的例子,当房屋大小为1250 f e e t 2 feet^

【高等代数笔记】线性空间(一到四)

3. 线性空间 令 K n : = { ( a 1 , a 2 , . . . , a n ) ∣ a i ∈ K , i = 1 , 2 , . . . , n } \textbf{K}^{n}:=\{(a_{1},a_{2},...,a_{n})|a_{i}\in\textbf{K},i=1,2,...,n\} Kn:={(a1​,a2​,...,an​)∣ai​∈K,i=1,2,...,n

c++习题30-求10000以内N的阶乘

目录 一,题目  二,思路 三,代码    一,题目  描述 求10000以内n的阶乘。 输入描述 只有一行输入,整数n(0≤n≤10000)。 输出描述 一行,即n!的值。 用例输入 1  4 用例输出 1  24   二,思路 n    n!           0    1 1    1*1=1 2    1*2=2 3    2*3=6 4

带头结点的线性链表的基本操作

持续了好久,终于有了这篇博客,链表的操作需要借助图像模型进行反复学习,这里尽可能的整理并记录下自己的思考,以备后面复习,和大家分享。需要说明的是,我们从实际应用角度出发重新定义了线性表。 一. 定义 从上一篇文章可以看到,由于链表在空间的合理利用上和插入、删除时不需要移动等优点,因此在很多场合下,它是线性表的首选存储结构。然而,它也存在某些实现的缺点,如求线性表的长度时不如顺序存储结构的

浙大数据结构:02-线性结构4 Pop Sequence

这道题我们采用数组来模拟堆栈和队列。 简单说一下大致思路,我们用栈来存1234.....,队列来存输入的一组数据,栈与队列进行匹配,相同就pop 机翻 1、条件准备 stk是栈,que是队列。 tt指向的是栈中下标,front指向队头,rear指向队尾。 初始化栈顶为0,队头为0,队尾为-1 #include<iostream>using namespace std;#defi