定理内容
中国剩余定理最早记载于《孙子算经》的“物不知数”问题,所以又叫做孙子剩余定理。
设
m
1
,
m
2
,
m
3
,
⋯
,
m
k
m_1,m_2,m_3,\cdots,m_k
m1,m2,m3,⋯,mk是
k
k
k个两两互素的正整数,则对于任意的
b
1
,
b
2
,
b
3
,
⋯
,
b
k
b_1,b_2,b_3,\cdots,b_k
b1,b2,b3,⋯,bk,同余式组:
{
x
≡
b
1
m
o
d
m
1
x
≡
b
2
m
o
d
m
2
x
≡
b
3
m
o
d
m
3
⋮
x
≡
b
k
m
o
d
m
k
\begin{aligned} \left\{ \begin{array}{lr} x\equiv b_1 \mod m_1 \\ x\equiv b_2 \mod m_2\\ x\equiv b_3 \mod m_3\\ \vdots\\ x\equiv b_k \mod m_k \end{array} \right. \end{aligned}
⎩⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎧x≡b1modm1x≡b2modm2x≡b3modm3⋮x≡bkmodmk
有且仅有一个解,为:
x
′
≡
b
1
⋅
M
1
′
⋅
M
+
b
2
⋅
M
2
′
⋅
M
2
+
⋯
+
b
k
⋅
M
k
′
⋅
M
k
m
o
d
m
x^\prime \equiv b_1 \cdot M_1^\prime \cdot M+b_2 \cdot M_2^\prime \cdot M_2 + \cdots + b_k \cdot M_k^\prime \cdot M_k \mod m
x′≡b1⋅M1′⋅M+b2⋅M2′⋅M2+⋯+bk⋅Mk′⋅Mkmodm
其中
M
i
=
∏
j
=
1
k
m
j
(
j
≠
i
)
,
M
i
′
⋅
M
i
≡
1
m
o
d
m
i
M_i=\prod \limits_{j=1}^{k} m_j(j\neq i), M_i^\prime \cdot M_i \equiv 1 \mod m_i
Mi=j=1∏kmj(j=i),Mi′⋅Mi≡1modmi.
对于任意一个同余式
x
≡
b
i
m
o
d
m
i
x \equiv b_i \mod m_i
x≡bimodmi,我们知道,对于
M
j
(
j
≠
i
)
M_j(j \neq i)
Mj(j=i)是
m
i
m_i
mi的倍数,所以,
b
j
⋅
M
j
′
⋅
M
j
≡
0
m
o
d
m
i
.
b_j \cdot M_j^\prime \cdot M_j \equiv 0 \mod m_i.
bj⋅Mj′⋅Mj≡0modmi.
x
′
≡
b
1
⋅
M
1
′
⋅
M
1
+
b
2
⋅
M
2
′
⋅
M
2
+
⋯
+
b
k
⋅
M
k
′
⋅
M
k
m
o
d
m
≡
b
i
⋅
M
i
′
⋅
M
i
m
o
d
m
i
≡
b
i
m
o
d
m
i
\begin{aligned} x^\prime &\equiv b_1 \cdot M_1^\prime \cdot M_1 +b_2 \cdot M_2^\prime \cdot M_2 +\cdots +b_k \cdot M_k^\prime \cdot M_k \mod m\\ &\equiv b_i \cdot M_i^\prime \cdot M_i \mod m_i\\ &\equiv b_i \mod m_i \end{aligned}
x′≡b1⋅M1′⋅M1+b2⋅M2′⋅M2+⋯+bk⋅Mk′⋅Mkmodm≡bi⋅Mi′⋅Mimodmi≡bimodmi
这说明
x
′
x^\prime
x′的确是同余式组的解,显然,若
x
′
′
x^{\prime \prime}
x′′是同于式组的解,那么也必然满足上式,说明
x
′
≡
x
′
′
m
o
d
m
x^\prime \equiv x^{\prime \prime} \mod m
x′≡x′′modm,即同余式组的解式唯一的。
c++代码演示
#include<iostream>
#include<vector>
using namespace std;
//We need the extedned gcd algorithm to compute the inverse of M
vector<int> exgcd(int a,int b,int s1=1,int s2=0,int t1=0,int t2=1){
int r=a%b;
if(r==0){
return {b,s2,t2};
}
int q=a/b;
int s3=-q*s2+s1;
int t3=-q*t2+t1;
return exgcd(b,r,s2,s3,t2,t3);
}
//Warnning: the elements in vector ms must be coprime!
int crt(vector<int> ms,vector<int> bs){
vector<int> Ms(ms.size());
vector<int> Ms_prime(ms.size());
int m=1;
for(auto i:ms){
m=m*i;
}
for(int i=0;i<ms.size();i++){
Ms[i]=m/ms[i];
auto temp=exgcd(Ms[i],ms[i]);
Ms_prime[i]=temp[1];
cout<<temp[1]<<endl;
}
int res=0;
for(int i=0;i<ms.size();i++){
res+=bs[i]*Ms[i]*Ms_prime[i]%m;
}
return res;
}
int main(){
vector<int> ms={3,5,7};
vector<int> bs={2,4,6};
int res=crt(ms,bs);
cout<<res<<endl;
}