乘法逆元

首先是我自己的一些理解:乘法逆元类比倒数,若x乘上y在模p的意义下为1,则①y为x在模p的意义下的乘法逆元,记作xy≡1(mod p),其中②y%p为x的乘法逆元(划线的是乘法逆元的两种表示)。

ps:只有两个数(x和p)互质才有乘法逆元;对于上面的式子,当p为素数时,x的乘法逆元唯一。

然后是关于乘法逆元存在的意义: 

• (a + b)%m = (a%m + b%m)%m
• (a − b)%m = (a%m − b%m)%m
• (a × b)%m = (a%m) × (b%m)%m

首先上面的三个式子是关于取模的一些运算法则,其中缺少除法运算,这是因为按照我们的逻辑来进行取模除法运算是不可行的(

例如3/4%5),所以定义了逆元,通过这种运算就可以算出3/4%5的值为2,即2为3在模5意义下的逆元。

再解释一些求乘法逆元的方法:第一种就是扩展欧几里得,条件为两数互质,单次复杂度大约是log级别的吧,注意扩展欧几里得求出的解中很可能有负数,若题目说求最小正整数解(参照luogu同余方程的题面),那么可以用(x+膜数)%膜数来转化(记住即可,证明比较麻烦);

第二种是费马小定理,这个要求模数p为素数才可以,还需要配合快速幂使用,单次复杂度同样是log级别;

第三种是一种线性的方法,条件是模数p为素数,且p必须要大于另一个数。

代码会陆续贴上。

第一种(类模板(需要一点的转化https://www.luogu.org/problemnew/solution/P1082):

#include<iostream>
using namespace std;

int a, b;

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

int main() {
	int x, y;
	cin >> a >> b;
	exgcd(a, b, x, y);
	cout << (x+b)%b;
	return 0;
}
//b > a

第三种:

inv[1] = 1; 
for (i = 2; i < p; i++)
	inv[i] = (p-p/i)*inv[p%i]%p;
//在p为质数的情况下可以求出[1,p)所有数的逆元 

另外,可以利用上面的方法实现O(n)预处理,O(1)查询组合数取模,博客地址:

https://blog.csdn.net/qq_38234381/article/details/81532093

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值