算法学习笔记-逆元

前言:

还记得小学学的倒数吗?倒数的定义大概是若 ax=1,则称 xa 的倒数。而逆元,其实可以看做在模意义下的倒数。也就是 ax1(modp),且 ap 互质,则称 xa 在模 p 意义下的乘法逆元,记作 a1。本文就将简要介绍求逆元的三种常用方法。

例题:

给定正整数 np,求 n 以内正整数在模 p 意义下的乘法逆元。

保证 p 是质数。

解法:

1.费马小定理:

费马小定理的定义:

对于任意正整数 a 和质数 p,有 ap11(modp)

可以发现,费马小定理的式子很像逆元,考虑把它转化一下,变成:

a×ap21(modp)

可以发现,ap2 就等于上面的 x,即 ap2 就是 a 在模 p 意义下的乘法逆元,用快速幂求即可。

点击查看代码
int qpow(int a, int b, int mod)
{
	int ans = 1;
	a %= mod;
	while(b)
	{
		if(b & 1) ans *= a;
		a = a * a % mod;
		b >>= 1; 
	}
	return ans;
}

int inv(int a, int p)//求a在模p意义下的乘法逆元
{
	return qpow(a, p - 2, p);
} 

2.Exgcd

不知道 exgcd 的可以参考我的博客

考虑将原式转换为 ax+py=1 (注:y 是引入的一个整数,而且可能是负数),根据逆元的定义:ap 必须互质,也就是 gcd(a,p)=1,因此原方程一定有解,用 exgcd 求即可。

点击查看代码
void exgcd(int a, int b, int &x, int &y)
{
	if(b == 0)
	{
		x = 1; y = 0;
		return;
	}
	exgcd(b, a % b, y, x);
	y = a / b * x;
}
int inv(int a, int p)//求a在模p意义下的乘法逆元
{
	int x, y;
	return exgcd(a, p, x, y);
} 

3.线性递推:

很多时候,题目要求的都是像例题那样 1~n 的逆元,用上面两种办法可以达到较快的 O(nlogn) 的复杂度(其实费马小定理得复杂度应该为 O(nlogq)。不过有没有方法能在线性时间内求出呢?答案是有的。

注:下面笔者提供了两种介绍方法,前一种为严谨的数学证明,后一种是转化为 exgcd 的介绍,请读者根据需要自行阅读。

  1. 数学证明:

先给结论:{x=1a=1qa(pmoda)1otherwise

先把式子转化一下:

k=pa, b=pmoda

a=pbk

则原式就可以变成:

a(pa(pmoda)1)=a(kb1)

打开括号,变成:

xkb1=kmbkb1

k 消掉,得到:

(bp)b1

因为对于同余方程,增减带模数的项结果不发生改变,所以可以将 p 去掉,变为:

(bp)b1bb11(modm)

换句话说,a(qa(qmoda)1)=a(kb1)1(modm),即 qa(qmoda)1)=a(kb1=a1。】

  1. 其实仔细观察可以发现,上式其实与 exgcd 的结论的式子很像。加上之前逆元对 exgcd 的转化,就显而易见了,具体一点笔者也说不清,请读者自行脑补(大雾。

知道上面的结论,代码就好写了。用一个数组记录每个数的逆元,正序枚举,由于枚举到 i 时,1~i1 的逆元都已算出,因此 imodp 的逆元也能求出,便可以做到单次 O(1),总复杂度为 O(n)

1

点击查看代码
inv[1] = 1;//inv[i] = i^ -1  
cout << 1 << "\n";
for(int i = 2; i <= n; i++)
{
	inv[i] = (p - p / i) * inv[p % i] % p;//按公式计算。
	//之所以要p-p/i是因为除完之后是个负数,在后面的取模会有问题,因此按照负数取模的原理要减一下 
	cout << inv[i] << "\n";
}

总结:

至此,逆元就告一段落了,文中的三种方法都有不错的时间复杂度,在应用中请根据实际情况选择,希望本文能帮助到您。

鉴于笔者也是蒟蒻,文中给出的部分推导过程与表述可能不严谨,欢迎大佬在评论区指出。
同时如果您对文章内容有不理解的地方,欢迎随时提问。

posted @   zhangxiao666  阅读(85)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示