乘法逆元详解【费马小定理+扩展欧几里得算法】

本文详细介绍了乘法逆元的概念及四种求解方法,包括费马小定理、扩展欧几里得算法、递推计算阶乘逆元及连续数逆元的方法,并提供了相应的编程实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

乘法逆元

何为乘法逆元?

对于两个数a,pa,pa,pgcd⁡(a,p)=1\gcd(a,p)=1gcd(a,p)=1则一定存在另一个数bbb,使得ab≡1(mod  p)ab\equiv1(\mod p)ab1(modp),并称此时的bbbaaa关于111ppp的乘法逆元。我们记此时的bbbinv(a)inv(a)inv(a)a−1a^{-1}a1

举个例子:5×3≡1(mod  14)5\times 3\equiv1(\mod 14)5×31(mod14),我们称此时的333555关于111141414的乘法逆元。

如何求乘法逆元?

方法一:费马小定理

费马小定理:当有两数a,pa,pa,p满足gcd⁡(a,p)=1\gcd(a,p)=1gcd(a,p)=1ppp是质数时,则有ap≡a(mod  p)a^{p}\equiv a(\mod p)apa(modp)

变一下形:a⋅ap−2≡1(mod  p)a\cdot a^{p-2}\equiv1(\mod p)aap21(modp)。是不是和上面的乘法逆元的定义是相似的?

所以,我们可以使用快速幂求出ap−2a^{p-2}ap2,即求出aaa的逆元。

方法二:扩展欧几里得算法

由定义可知:ab≡1(mod  p)ab\equiv 1(\mod p)ab1(modp),这个式子等价于已知a,pa,pa,p求一个二元一次不定方程ab=kp+1ab=kp+1ab=kp+1,移一下项得:ab−kp=1ab-kp=1abkp=1。这东西不是扩展欧几里得算法?

方法三:递推计算阶乘的逆元

当我们要计算一大串连续的阶乘的逆元时,采用费马小定理或扩展欧几里得算法就有可能超时,所以我们必须采用一个更快的算法。

fi=i!f_i=i!fi=i!,则可得:inv(fi+1)≡inv(fi⋅(i+1))(mod  p)inv(f_{i+1})\equiv inv(f_i\cdot (i+1))(\mod p)inv(fi+1)inv(fi(i+1))(modp)

我们将(i+1)(i+1)(i+1)乘过去,则有:inv(fi)≡inv(fi+1)⋅(i+1)(mod  p)inv(f_{i})\equiv inv(f_{i+1})\cdot(i+1)(\mod p)inv(fi)inv(fi+1)(i+1)(modp)

自然我们就得出递推式。

方法四:递推计算连续的数的逆元

当我们要计算连续的数的逆元时,我们可以采用以下递推式:inv(i)=(p−⌊pi⌋)×inv(pmod  i)mod  pinv(i)=(p-\lfloor\frac{p}{i}\rfloor)\times inv(p\mod i)\mod pinv(i)=(pip)×inv(pmodi)modp

UPD@2019.10.9:补上这个式子的证明

证明:设t=⌊pi⌋,k=pmod  it=\lfloor\frac{p}{i}\rfloor,k=p\mod it=ip,k=pmodi,那么显然有t×i+k≡0(mod  p)t\times i+k\equiv 0(\mod p)t×i+k0(modp)

变形可得−t×i≡k(mod  p)-t\times i\equiv k(\mod p)t×ik(modp)

两边同时除以ikikik得到−t×1k≡1i(mod  p)-t\times\frac{1}{k}\equiv\frac{1}{i}(\mod p)t×k1i1(modp)

inv(i)≡−t×inv(k)(mod  p)inv(i)\equiv-t\times inv(k)(\mod p)inv(i)t×inv(k)(modp)

所以有inv(i)=(p−⌊pi⌋)×inv(pmod  i)mod  pinv(i)=(p-\lfloor\frac{p}{i}\rfloor)\times inv(p\mod i)\mod pinv(i)=(pip)×inv(pmodi)modp

乘法逆元的作用?

我们由费马小定理可得:a⋅ap−2≡1(mod  p)a\cdot a^{p-2}\equiv 1(\mod p)aap21(modp)

所以:ap−2≡a−1≡1a(mod  p)a^{p-2}\equiv a^{-1}\equiv\frac{1}{a}(\mod p)ap2a1a1(modp)

我们又知道模运算的乘法结合律:ba≡b⋅a−1≡b⋅ap−2(mod  p)\frac{b}{a}\equiv b\cdot a^{-1}\equiv b\cdot a^{p-2}(\mod p)abba1bap2(modp)

所以我们可以知道:aaa除以一个数模ppp,等于aaa乘这个数的乘法逆元模ppp

编程实现

费马小定理:

long long PowMod(long long a,int b) {
	long long ret=1;
	while(b) {
		if(b&1)ret=ret*a%Mod;
		a=a*a%Mod;
		b>>=1;
	}
	return ret;
}

程序内调用PowMod(a,Mod-2)即可。

扩展欧几里得算法:

long long extend_gcd(long long a,long long b,long long &x,long long &y) {
	if(a==0&&b==0)
		return -1ll;
	if(b==0)
	{
		x=1ll;
		y=0ll;
		return a;
	}
	long long d=extend_gcd(b,a%b,y,x);
	y-=a/b*x;
	return d;
}
long long mod_reverse(long long a,long long n) {
    long long x,y,d=extend_gcd(a,n,x,y);
    if(d==1) {
	    if(x%n<=0)return x%n+n;
		else return x%n;
	} else return -1ll;
}

递推计算阶乘的逆元:

f[0]=1;
for(int i=1;i<=N;i++)
	f[i]=f[i-1]*i%Mod;
inv[0]=1;
inv[N]=PowMod(f[N],Mod-2);
for(int i=N-1;i>0;i--)
	inv[i]=inv[i+1]*(i+1)%Mod;

递推计算连续的数的逆元:

inv[1]=1;
for(int i=2;i<=N;i++)
	inv[i]=(Mod-Mod/i)*inv[Mod%i]%Mod;
<think>我们已知费马小定理:如果 \( p \) 是一个质数,而整数 \( a \) 不是 \( p \) 的倍数,那么有 \( a^{p-1} \equiv 1 \pmod{p} \)。 由费马小定理可得:\( a \cdot a^{p-2} \equiv 1 \pmod{p} \)。 因此,在模 \( p \) 的意义下,\( a \) 的乘法逆元就是 \( a^{p-2} \)(这里要求 \( p \) 是质数且 \( a \) 不是 \( p \) 的倍数)。 计算乘法逆元的步骤: 1. 确认模数 \( p \) 是质数,且 \( a \) 不是 \( p \) 的倍数(即 \( a \mod p \neq 0 \))。 2. 使用快速幂算法计算 \( a^{p-2} \mod p \),结果即为 \( a \) 模 \( p \) 的乘法逆元。 注意:如果 \( a \) 是 \( p \) 的倍数,则乘法逆元不存在。 快速幂算法(参考引用[4]): 快速幂通过将指数进行二进制分解来高效计算幂模。具体步骤如下: - 初始化结果变量为1。 - 当指数不为0时: - 如果指数是奇数,将结果乘以底数并取模。 - 底数平方并取模。 - 指数右移一位(即除以2)。 示例代码(引用[4]中的代码): ```cpp #include<bits/stdc++.h> using namespace std; #define int long long int qp(int a, int b, int p) { int res = 1; for (; b; b >>= 1) { if (b & 1) res = (res * a) % p; a = (a * a) % p; } return res; } signed main() { int tt; cin >> tt; while (tt--) { int a, p; cin >> a >> p; if (a % p == 0) { cout << "impossible" << endl; } else { // 计算逆元:a^(p-2) mod p int res = qp(a, p-2, p); cout << res << endl; } } return 0; } ``` 解释: - 函数 `qp` 是快速幂函数,计算 \( a^b \mod p \)。 - 在主函数中,首先判断 `a % p` 是否为0,如果为0则输出"impossible",否则计算 \( a^{p-2} \mod p \) 并输出。 注意事项: - 费马小定理只适用于模数为质数的情况。如果模数不是质数,则需要使用扩展欧几里得算法(如引用[2]和[5]所述)。 - 当模数 \( p \) 很大时,快速幂算法效率很高(时间复杂度为 \( O(\log p) \))。 总结:使用费马小定理乘法逆元的前提是模数 \( p \) 为质数且 \( a \) 与 \( p \) 互质(即 \( a \) 不是 \( p \) 的倍数)。计算方法为 \( a^{p-2} \mod p \)。 §§相关问题§§ 1. 如果模数不是质数,如何求乘法逆元? 2. 快速幂算法的时间复杂度是多少?它是如何工作的? 3. 费马小定理的证明过程是怎样的? 4. 乘法逆元在密码学中有哪些应用?</think>### 使用费马小定理计算乘法逆元 费马小定理是求解模运算中乘法逆元的重要方法,特别适用于**模数为质数**的场景。其核心原理和计算步骤如下: #### 1. **费马小定理** 若 \( p \) 是质数,且整数 \( a \) 满足 \( \gcd(a, p) = 1 \)(即 \( a \) 不是 \( p \) 的倍数),则: $$ a^{p-1} \equiv 1 \pmod{p} $$ 变形后可得: $$ a \cdot a^{p-2} \equiv 1 \pmod{p} $$ 因此,**\( a \) 模 \( p \) 的乘法逆元**为: $$ a^{-1} \equiv a^{p-2} \pmod{p} $$ #### 2. **计算步骤** 1. **验证条件**: - \( p \) 必须是质数。 - \( a \not\equiv 0 \pmod{p} \)(否则逆元不存在)。 2. **计算 \( a^{p-2} \mod p \)**: - 使用**快速幂算法**高效计算(时间复杂度 \( O(\log p) \))。 #### 3. **快速幂算法实现** ```python def mod_inverse(a, p): # 验证条件 if a % p == 0: # a是p的倍数,逆元不存在 return None # 计算 a^{p-2} mod p result = 1 exponent = p - 2 base = a % p while exponent: if exponent & 1: # 指数为奇数 result = (result * base) % p base = (base * base) % p # 底数平方 exponent >>= 1 # 指数右移(整除2) return result ``` #### 4. **示例** - 求 \( a=3 \) 在模 \( p=11 \)(质数)下的逆元: $$ 3^{-1} \equiv 3^{11-2} = 3^9 \pmod{11} $$ 计算过程: $$ 3^1 \equiv 3, \quad 3^2 \equiv 9, \quad 3^4 \equiv 81 \equiv 4, \quad 3^8 \equiv 4^2 \equiv 16 \equiv 5, \quad 3^9 \equiv 5 \times 3 \equiv 15 \equiv 4 \pmod{11} $$ 验证: \( 3 \times 4 = 12 \equiv 1 \pmod{11} \),正确。 #### 5. **注意事项** - **适用条件**:仅当 \( p \) 为质数且 \( a \not\equiv 0 \pmod{p} \) 时有效。 - **效率**:快速幂算法在 \( O(\log p) \) 时间内完成计算,适合大数运算。 - **扩展**:若 \( p \) 非质数,需改用**扩展欧几里得算法**[^2][^5]。 #### 6. **代码验证(引用[4])** ```cpp #include<bits/stdc++.h> using namespace std; int qp(int a, int b, int p) { int res = 1; for (; b; b >>= 1) { if (b & 1) res = (res * 1LL * a) % p; // 防止溢出 a = (a * 1LL * a) % p; } return res; } int main() { int a = 3, p = 11; if (a % p == 0) cout << "impossible"; else cout << qp(a, p-2, p); // 输出 4 return 0; } ``` > **关键点**:费马小定理逆元计算转化为模幂运算,快速幂通过二进制分解指数显著提升效率[^4]。 --- ###
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值