MisakaMKT

C++实现,拓展中国剩余定理——解同余方程组(理论证明和代码实现)

拓展中国剩余定理

前言

记得半年前还写过关于拓展中国剩余定理的博客。。。不过那时对其理解还不是比较深刻,写的也比较乱。

于是趁学校复习之机,再来重温一下拓展中国剩余定理(以下简称ExCRT)

记得半年前还写过关于拓展中国剩余定理的博客。。。不过那时对其理解还不是比较深刻,写的也比较乱。

于是趁学校复习之机,再来重温一下拓展中国剩余定理(以下简称ExCRT)

一些理论准备

拓展欧几里得解不定方程

对于不定方程ax+by=gcd(a,b),视a,b为常数,我们有一种通用的方法来求一组特解:

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

注:这种方法只能求一种特解,对于求所有的解请读者自行百度。这个函数运行到最后,x,y便是一组特解,返回值为gcd(a,b)

于是我们可以将这个方程推广为解类似于ax+by=c这个不定方程,方法就是先求出方程ax+by=gcd(a,b)的解,之后将等式两边同时乘以c/gcd(a,b)。便转换为:

axc/gcd(a,b)+byc/gcd(a,b)=c,x=xc/gcd(a,b),y=yc/gcd(a,b).

而如果c并不能被gcd(a,b)整除,那么此不定方程无解

理论证明

对于同余方程:

{xr1(modm1)xr2(modm2)......xrk(modmk)

我们可以考虑k=2的情况,也就是解如下方程:

{xr1(modm1)xr2(modm2)

由如上方程不难转换为以下形式

{x=k1m1+r1x=k2m2+r2

将两个式子合并可以得到:

k1m1k2m2=r2r1

对于这个不定方程,我们可以使用拓展欧几里得来求解。

先解出方程k1m1k2m2=gcd(m1,m2),于是可以得到

k1=k1(r2r1)/gcd(m1,m2),代入式子x=k1m1+r1便可以算出x的一组特解,设这个特解为x0,那么可以得到通解

x=x0+tlcm(m1,m2),于是我们便通过合并第1,2个同余式子得到了新的一个同余方程:xx0(modlcm(m1,m2))

将这个同余方程按照同样的方法与第三个同余式子合并,最后只剩下唯一一个式子xxk(modlcm(mi))

此时的答案便可以得出最小的答案。

代码实现

LL ExCRT() {
	LL M=m[1],R=r[1];
    //方便 理解代码的话
    //m可以看作上述x0,R可以看作lcm(m1,m2)
	for(LL i=2,d,x,y;i<=n;i++) {
		d=exgcd(M,m[i],x,y);//d为最大公约数
		if((R-r[i])%d) return -1;//无解的情况
		x=x*(R-r[i])/d%m[i];
		R-=x*M;
		M=M/d*m[i];
		R%=M;
	}
	return (R%M+M)%M;//最小的正整数解
}

写在后面

现在发现。。。ExCRT好简单

posted on   MisakaMKT  阅读(1196)  评论(0编辑  收藏  举报

编辑推荐:
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
阅读排行:
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 上周热点回顾(2.17-2.23)

导航

统计信息

点击右上角即可分享
微信分享提示