论中国剩余定理(CRT)

本文讲解了如何使用中国剩余定理解决奥数中给定余数的最小整数问题,涉及暴力求解、线性筛的优化,以及利用乘法逆元的计算过程。

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

1.前言


本文将介绍中国剩余定理(即CRT),前置知识为同余运算和乘法逆元,如果不会可以看我关于乘法逆元的博客
如果你刚学习完逆元,也建议阅读本文,CRT是逆元的一种具体应用)


2.问题


小学奥数里有这样一个问题,给定n个整数ai,mi(mi之间互质)
使得存在一个整数x满足
x mod m1 = a1
x mod m2 = a2

......
x mod mn = an

给定x除以n个整数的余数
求最小的x


3暴力求解


我们先考虑暴力求解
枚举每一个数,判断一下是否符合要求
但是这样太慢了,会TLE
我们又可以优化一下,借用一下线性筛(如果不会可以去我主页看)
但是很可惜,依旧TLE
我要优化!


4中国剩余定理


先说结论,设M为所有m的乘积
设Mi为M/mi,即除mi外所有m的乘积
设ti为Mi的乘法逆元
令bi = aiMiti
方程的解x为所有bi的和
最后模上M,求出最小整数解
看着很复杂,看不懂怎么办
没逝,看完证明就明白了
首先,我们要让bi mod mi = ai,又要让 bi mod mj(此处包括下文j不等于i)= 0,这样bi加起来,余数直接相加,符合要求
要让bi mod mi = ai,直接让bi = ai不就行了吗
可是这样的话就没法满足bi mod mj = 0
我们要做的是让bi = ai*ci使得ci mod mi = 1,并且c为mj的倍数
mi之间互质,所以c最小也是mj的乘积,但是此时c mod mi 不一定等于 1
这时,乘法逆元的作用就显现出来了,ci还要乘上它的乘法逆元,这下完美了
但是此时x不一定为最小整数解,根据同余运算,只要模上mi的乘积就行了
现在,得出的结果和公式略有不同,公式先求出了mi的乘积M
对于每个没乘上乘法逆元的ci(即公式中的Mi)只要用M/mi就可以,这样直接优化掉了一维时间复杂度,特别快,不怕超时
所以说,学算法可以直接看公式,但是一定要自己推一遍,要不然特别抽象,能看懂就怪了
有了CRT以后,上述问题可以直接转化为求逆元+模拟
下面附上代码(题目为洛谷P1945CRT模板)
(顺便说一下,因为CRT极快,所以求逆元甚至可以直接枚举,但是不推荐这么做)

#include<bits/stdc++.h>
using namespace std;
long long n;
long long M = 1;
long long m[114514];
long long a[114514];
long long b[114514];
long long x,y,res,ans;
long long xx;
void exgcd(long long a,long long b){//求逆元 
	if(b==0){
		x = 1;
		y = 0;
	}else{
		exgcd(b,a%b);
		xx = x;
		x = y;
		y = xx-(a/b)*y;
	}
}
int main(){
	scanf("%lld",&n);
	for(int i = 1;i<=n;i++){//输入 
		scanf("%lld%lld",&b[i],&a[i]);
		M*=a[i];
	}
	for(int i = 1;i<=n;i++){//累加ans 
		m[i] = M/a[i];//求Mi 
		exgcd(m[i],a[i]);//求Mi关于ai的逆元 
		ans = ((ans+m[i]*b[i]*x)%M+M)%M;//加,别忘了模 
	}
	printf("%lld\n",(ans+M)%M);//记得用%lld 
	return 0;
}


5总结


CRT都学会了,但是EXCRT(用于解决mi不互质)还不会,那可是紫题啊,本蒟蒻不会
可是当初看CRT的时候都觉得难,不会,人是会进步的,我在这里叕挖坑,以后会补EXCRT的
本文如有错误请各位神犇提出,我会尽快改正
 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值