中国剩余定理

前言

本文介绍了中国剩余定理及其扩展,可以用于求解一元线性同余方程组。
具体来说,它们能解决如下问题:

\[\begin{cases} x&\equiv r_1\pmod{m_1}\\ x&\equiv r_2\pmod{m_2}\\ &\vdots\\ x&\equiv r_n\pmod{m_n} \end{cases}\]

中国剩余定理(CRT)

CRT 在求解上文提到的问题时有个限制条件,就是 \(\forall 1\le i<j\le n,\gcd(m_i,m_j)=1\),即模数两两互质。
至于为什么会有这个限制我们会在下文解释。

求解过程

我们令 \(\displaystyle m=\operatorname{lcm}(m_1,m_2,\cdots,m_n)=\prod_{i=1}^nm_i\)
则原方程有一个唯一解 \(x\equiv x_0\pmod m\)

我们不妨设 \(\displaystyle x_0=\sum_{i=1}^nc_ir_i\)
若所有都 \(c_i\) 满足

\[\begin{cases} c_i\equiv1\pmod{m_j},&j=i\\ c_i\equiv0\pmod{m_j},&\text{otherwise} \end{cases}\]

即可满足原式。
\(c_i\equiv1\pmod{m_i},\dfrac{m}{m_i}\mid c_i\)

我们不妨令 \(m_i'=\dfrac{m}{m_i}\),再令 \(c_i=k_im_i'\),就有 \(k_im_i'\equiv1\pmod{m_i}\),所以 \(k_i=m_i'^{-1}\)
因此,\(c_i=m_i'm_i'^{-1}\)。(注意此处 \(c_i\) 不能对 \(m_i\) 取模)

因此 \(\displaystyle x_0=\sum_{i=1}^nm_i'm_i'^{-1}r_i\)

顺便证明下 \(x\equiv x_0\pmod{m}\) 是该方程组的唯一解。
证明:

\(x_0'\) 也满足所有方程,且 \(x_0'\not\equiv x_0\pmod{m}\)
显然有 \(x_0'\equiv r_i\equiv x_0\pmod{m_i}\),所以 \(m_i\mid(x_0'-x_0)\)
\(m\mid(x_0'-x_0)\),故 \(x_0'\equiv x_0\pmod{m}\),矛盾。
\(x\equiv x_0\pmod{m}\) 是该方程组的唯一解。

上述就是 CRT 的求解方法,下面概括下具体过程:

  • 计算 \(\displaystyle m=\prod_{i=1}^nm_i\)
  • 对于第 \(i\) 个方程:
    • 计算 \(m_i'=\dfrac{m}{m_i}\)
    • 计算 \(m_i'\) 在模 \(m_i\) 意义下的逆元 \(m_i'^{-1}\)
    • 计算 \(c_i=m_i'm_i'^{-1}\)(不要对 \(m_i\) 取模)。
  • 最终方程组在模 \(m\) 意义下的唯一解为 \(\displaystyle x\equiv\sum_{i=1}^nc_ir_i\pmod{m}\)

实现

int CRT(int n,int *r,int *m){
	int M=1,ans=0;
	for(int i=0;i<n;++i)M*=m[i];
	for(int i=0;i<n;++i){
		int m_=M/m[i],invm_,tmp;
		exgcd(m_,m[i],invm_,tmp);//m_*invm_ mod m[i] =1
		ans=(ans+r[i]*m_*invm_%M)%M;
	}
	return (ans%M+M)%M;
}
//n 是方程个数,r[] 是余数数组,m[] 是模数数组
//exgcd(a,b,x,y) 用于求解 ax+by=gcd(a,b) 的问题,此处用于求逆元 

扩展中国剩余定理(exCRT)

注意到在 CRT 求解时需要计算 \(m_i'\) 关于 \(m_i\) 的逆元,这就要求 \(\gcd(m_i',m_i)=1\)
但如果模数不满足两两互质呢?这时候 CRT 就不能正常求解了,所以 exCRT 就上场了。

求解过程

考虑最原始的办法:将两个方程合并成一个方程。
考虑如下问题

\[\begin{cases} x&\equiv r_1\pmod{m_1}\\ x&\equiv r_2\pmod{m_2} \end{cases}\]

我们需要给出一个解或判断无解。

把其转化成不定方程形式,则有 \(x=m_1x_1+r_1=m_2x_2+r_2\),即 \(m_1x_1-m_2x_2=r_2-r_1\)
根据裴蜀定理,当 \(\gcd(m_1,m_2)\not\mid (r_2-r_1)\) 时,原方程无解,否则有解。
若有解,则可以用 exgcd 求出一组可行解 \((x_1,x_2)\),则合并后的方程为 \(x\equiv m_1x_1+r_1\pmod{\operatorname{lcm}(m_1,m_2)}\)

实现

int exCRT(int n,int *r,int *m){
	int r1=r[0],r2,m1=m[0],m2,x1,x2,d;
	for(int i=1;i<n;++i){
		r2=r[i],m2=m[i];
		if((r2-r1)%(d=exgcd(m1,m2,x1,x2))!=0)return -1;
        int M=m1*m2/d;
        x1*=(r2-r1)/d;
		r1=(m1*x1+r1)%M;
		m1=M;
	}
	return (r1%M+M)%M;
}
//exgcd(a,b,x,y) 求解 ax+by=gcd(a,b) 并返回 gcd(a,b)
//当原方程组无解时返回 -1 
posted @ 2025-07-23 18:47  LXcjh4998  阅读(47)  评论(0)    收藏  举报