孙子定理及扩展孙子定理

中国剩余定理 (Chinese Remainder Theorem)

CRT是解决下列同余方程问题的, m i , m j m_i,m_j mi,mj两两互质。

孙子定理及扩展孙子定理_mysql

该定理只需要用到两个取余知识点:

1. a % b = c → ( a + k b ) % b = c a\%b=c\rightarrow (a+kb)\%b=c a%b=c(a+kb)%b=c

2. a % b = c → ( k a ) % b = k c   ( k c < b ) a\%b=c\rightarrow (ka)\%b=kc\ (kc<b) a%b=c(ka)%b=kc (kc<b)

该问题当模数两两互质必有解。

M i M_i Mi是除了 m i m_i mi之外的所有 m j m_j mj l c m = ∏ j = 1 n m [ j ] m [ i ] lcm=\dfrac{\prod\limits_{j=1}^nm[j]}{m[i]} lcm=m[i]j=1nm[j]

M i t ≡ 1 ( m o d m i ) M_it\equiv 1\pmod{m_i} Mit1(modmi)

⇒ M i t + m i y = 1 \Rightarrow M_it+m_iy=1 Mit+miy=1

e x g c d exgcd exgcd可解出 t t t

这个满足 x ≡ a i ( m o d m i ) x\equiv a_i\pmod{m_i} xai(modmi)的式子,我们先找到该式余1的解: M i t M_it Mit

然后由知识 2 2 2可得, a i × M i × t ( m o d m i ) = a i a_i\times M_i\times t\pmod{m_i}=a_i ai×Mi×t(modmi)=ai

最后的答案就是: ∑ i = 1 n a i M i t i ( m o d M ) \sum\limits_{i=1}^n a_iM_it_i\pmod{M} i=1naiMiti(modM)

该解是最小正整数解。

代码

void exgcd(ll a,ll b,ll &x,ll &y){
	//ax+by=1
	if(!b){
		x=1,y=0;
		return;
	}
	exgcd(b,a%b,y,x); 
	y-=(a/b)*x;
}
ll m[N],a[N];//m[i] modulus (relatively prime) a[i] remainder
ll crt(int n){ //Chinese Remainder Theorem  (nlogM)
	ll M=1;//product of modulus
	for(int i=1;i<=n;i++)
		scanf("%lld%lld",&m[i],&a[i]),M*=m[i];
	ll ans=0;
	for(int i=1;i<=n;i++){
		ll x,y;
		ll u=M/m[i];// Inverse
		exgcd(u,m[i],x,y);// ux+m[i]y=1
		ans=(ans+1LL*a[i]*u*x%M)%M; //sum of a[i]*u*x
	}
	return (ans%M+M)%M;//Minimum positve integer
}

扩展中国剩余定理

假设我们已经求出前 i − 1 i-1 i1个方程的解 x x x,且令 M = l c m { m j } j ∈ [ 1 , i − 1 ] M=lcm\{m_j\} j\in[1,i-1] M=lcm{mj}j[1,i1]

x x x的通解为: x + k M x+kM x+kM

对于第 i i i个方程: ( x + k M ) ≡ a i ( m o d m i ) (x+kM)\equiv a_i\pmod{m_i} (x+kM)ai(modmi)

即: k M = ( a i − x ) ( m o d m i ) kM=(a_i-x)\pmod{m_i} kM=(aix)(modmi)

k M + m i y = ( a i − x ) kM+m_iy=(a_i-x) kM+miy=(aix)

e x g c d exgcd exgcd可解得: k k k

所以前 i i i个方程的解 x ′ = x + k M x'=x+kM x=x+kM,然后更新 M = l c m ( M , m i ) M=lcm(M,m_i) M=lcm(M,mi)进入下个方程即可。

代码

ll exgcd(ll a,ll b,ll &x,ll &y){
	//ax+by=1
	if(!b){
		x=1,y=0;
		return a;
	}
	ll g=exgcd(b,a%b,y,x); 
	y-=(a/b)*x;
	return g;
}
ll qmul(ll a,ll b,ll m){
	ll s=0;
	while(b){
		if(b&1) s=(s+a)%m;
		a=(a+a)%m;
		b>>=1;
	}
	return s;
}
ll m[N],a[N];//m[i] modulus (relatively prime) a[i] remainder
ll excrt(int n){ //Chinese Remainder Theorem  (nlogM)
	ll M=1,ans=0;//product of modulus
	for(int i=1;i<=n;i++){
		ll x,y,c=(a[i]-ans%m[i]+m[i])%m[i];
		ll g=exgcd(M,m[i],x,y);
		if(c%g) return -1;//no answer
		ll g1=m[i]/g,g2=c/g;
		x=qmul(x,g2,g1);
		ans+=x*M;
		M*=g1;
		ans=(ans%M+M)%M;
	}
	return (ans%M+M)%M;//Minimum positve integer
}

Hint

{ k i x = a i ( m o d m i ) } \{k_ix=a_i\pmod{m_i}\} {kix=ai(modmi)}

类似 e x c r t excrt excrt

已知前 i − 1 i-1 i1个方程的通解: x + t M x+tM x+tM

k i ( x + t M ) = a i ( m o d m i ) k_i(x+tM)=a_i\pmod{m_i} ki(x+tM)=ai(modmi)

( k i M ) t + m i y = a i − k i x (k_iM)t+m_iy=a_i-k_ix (kiM)t+miy=aikix

e x g c d exgcd exgcd可解得 t t t

因此可求出 x x x


记忆方法

上述两个定理的关键都是: m i x + M i y = c m_ix+M_iy=c mix+Miy=c 解出 x x x

一个是: M i x + m i y = 1 M_ix+m_iy=1 Mix+miy=1

a n s = ∑ a i M i x ( m o d M ) ans=\sum a_iM_ix \pmod{M} ans=aiMix(modM)

一个是: M i x + m i y = ( a i − a n s ) M_ix+m_iy=(a_i-ans) Mix+miy=(aians)

a n s = ∑ M i x ( m o d M ) ans=\sum M_ix \pmod{M} ans=Mix(modM)


参考文章

具体证明可参考这篇文章

传送门

传送门


习题

P4777 【模板】扩展中国剩余定理(EXCRT)

P1495 【模板】中国剩余定理(CRT)/曹冲养猪

ABC 193 E(EXCRT 板子)

POJ 1006 (CRT 板子)