- 中国剩余定理又称孙子定理
- 是处理一次同余方程组求解问题的一个基本结论
- 可以用于求解模线性方程组的解
中国剩余定理(CRT)
求解如下的方程组
⎩⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎧x≡b1(modm1)x≡b2(modm2)x≡b3(modm3)…x≡bn(modmn)
有M=∏i=1nmi
Mi=M/mi,yi≡Mi(modmi),yi是在模mi意义下的逆元
mi(1≤i≤n)两两互素
此方程组在modM意义下有唯一解
此解可表示为
x≡∑i=1naiMiyi(modM)
ll china(){
ll ans=0;
ll M=1;
for(int i=1;i<=n;++i){
M*=ai[i];
}
for(int i=1;i<=n;++i){
ll kk=M/ai[i];
ll x=0,y=0;
exgcd(kk,ai[i],x,y);
ans=(ans+bi[i]*kk*x)%M;
}
if(ans>0){
return ans;
}else{
return ans+M;
}
}
拓展中国剩余定理(EXCRT)
拓展中国剩余定理可以用于求解在中国剩余定理中mi(1≤i≤n)不互素的情况
求解如下的方程组
⎩⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎧x≡c1(modm1)x≡c2(modm2)x≡c3(modm3)…x≡cn(modmn)
mi(1≤i≤n)不保证两两互素
解题思路主要是将两两方程合并
最后化为一个方程组进行求解
首先考虑只有两个方程组的情况
{x≡c1(modm1)x≡c2(modm2)
有
x=k1×m1+c1……(1)
x=k2×m2+c2
k1×m1+c1=k2×m2+c2
k1×m1=k2×m2+(c2−c1)
此时,k1×m1−k2×m2=c2−c1,(m1,m2)∣(c2−c1)否则方程无解
令 d=(m1,m2)
dm1×k1=dm2×k2+dc2−c1
dm1×k1≡dc2−c1(moddm2)
在此,我们消掉了k1
等式两边同除dm1
由同余的同除性质(第八条),详情
k1≡dc2−c1×inv(dm1,dm2)(moddm2)
inv(x,y)表示x在模y意义下的逆元
有
k1=dc2−c1×inv(dm1,dm2)+y×dm2
将上式代回(1)
x=dc2−c1×inv(dm1,dm2)×m1+y×dm1×m2+c1
x≡dc2−c1×inv(dm1,dm2)×m1+c1(moddm1×m2)
此时发现这个式子又是x≡c(modm)的形式
其中
m=dm1×m2
c=dc2−c1×inv(dm1,dm2)×m1+c1
当最只有一个方程组时,c自然为答案
ll excrt(){
ll M=ai[1];
ll ans=bi[1];
for(int i=2;i<=n;++i){
ll e=bi[i]-ans;
ll x,y;
ll d=exgcd(M,ai[i],x,y);
if(e%d!=0){ return -1;}
ll nowm=ai[i]/d;
x=(x%nowm+nowm)%nowm;
x=(mul(x,(e/d%nowm+nowm)%nowm,nowm)+nowm)%nowm;
ll newm=M*nowm;
ans=(ans+mul(x,M,newm)+newm)%newm;
M=newm;
}
return ans;
}
ps:
坑:在计算机中,若有a<0,则a mod b仍然是负数,与数学中的定义不一致
所以,频繁的取+mod,再取mod操作是为了保证mod后为正整数,与数学中的定义保持一致
从另一角度理解代码中的exgcd
两方程组
{x≡c1(modm1)x≡c2(modm2)
同上化简
k1×m1−k2×m2=c2−c1
此时m1,m2不一定互质
令d=(m1,m2)
m1=m1′×d,m2=m2′×d,m1′,m2′互质
则exgcd(m1,m2,x,y)求解了
m1′×k1′+m2′×k2′=1的一个解
则上式k1×m1−k2×m2=c2−c1中的k1=k1′×dc2−c1+p×m2′,m2′=dm2