中国剩余定理 引入 「物不知数」问题:有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?
即求满足以下条件的整数:除以 3 3   余 2 2  ,除以 5 5   余 3 3  ,除以 7 7   余 2 2  。
该问题最早见于《孙子算经》中,并有该问题的具体解法。宋朝数学家秦九韶于 1247 年《数书九章》卷一、二《大衍类》对「物不知数」问题做出了完整系统的解答。上面具体问题的解答口诀由明朝数学家程大位在《算法统宗》中给出:
三人同行七十希,五树梅花廿一支,七子团圆正半月,除百零五便得知。
2   × 7 0   + 3   × 2 1   + 2   × 1 5   = 2 3 3   = 2   × 1 0 5   + 2 3 2 × 70 + 3 × 21 + 2 × 15 = 233 = 2 × 105 + 23  ,故答案为 2 3 23  。
定义 中国剩余定理 (Chinese Remainder Theorem, CRT) 可求解如下形式的一元线性同余方程组(其中 𝑛 1 , 𝑛 2 , ⋯ , 𝑛 𝑘 n 1 , n 2 , ⋯ , n k   两两互质):
⎧ { { { ⎨ { { { ⎩ 𝑥 ≡ 𝑎 1 ( m o d 𝑛 1 ) 𝑥 ≡ 𝑎 2 ( m o d 𝑛 2 ) ⋮ 𝑥 ≡ 𝑎 𝑘 ( m o d 𝑛 𝑘 ) { x ≡ a 1 ( mod n 1 ) x ≡ a 2 ( mod n 2 ) ⋮ x ≡ a k ( mod n k ) 上面的「物不知数」问题就是一元线性同余方程组的一个实例。
过程 计算所有模数的积 𝑛 n  ; 对于第 𝑖 i   个方程:计算 𝑚 𝑖   = 𝑛 𝑛 𝑖 m i = n n i  ; 计算 𝑚 𝑖 m i   在模 𝑛 𝑖 n i   意义下的 逆元  𝑚 − 1 𝑖 m i − 1  ; 计算 𝑐 𝑖   = 𝑚 𝑖 𝑚 − 1 𝑖 c i = m i m i − 1  (不要对 𝑛 𝑖 n i   取模 )。  方程组在模 𝑛 n   意义下的唯一解为:𝑥   = ∑ 𝑘 𝑖 = 1 𝑎 𝑖 𝑐 𝑖 ( m o d 𝑛 ) x = ∑ i = 1 k a i c i ( mod n )  。 实现 C++ Python 
LL   CRT ( int   k ,   LL *   a ,   LL *   r )   { 
   LL   n   =   1 ,   ans   =   0 ; 
   for   ( int   i   =   1 ;   i   <=   k ;   i ++ )   n   =   n   *   r [ i ]; 
   for   ( int   i   =   1 ;   i   <=   k ;   i ++ )   { 
     LL   m   =   n   /   r [ i ],   b ,   y ; 
     exgcd ( m ,   r [ i ],   b ,   y );    // b * m mod r[i] = 1 
     ans   =   ( ans   +   a [ i ]   *   m   *   b   %   n )   %   n ; 
   } 
   return   ( ans   %   n   +   n )   %   n ; 
} 
def   CRT ( k ,  a ,  r ): 
    n  =  1 
    ans  =  0 
    for  i  in  range ( 1 ,  k  +  1 ): 
        n  =  n  *  r [ i ] 
    for  i  in  range ( 1 ,  k  +  1 ): 
        m  =  n  //  r [ i ] 
        b  =  y  =  0 
        exgcd ( m ,  r [ i ],  b ,  y )   # b * m mod r[i] = 1 
        ans  =  ( ans  +  a [ i ]  *  m  *  b  %  n )  %  n 
    return  ( ans  %  n  +  n )  %  n 
证明 我们需要证明上面算法计算所得的 𝑥 x   对于任意 𝑖   = 1 , 2 , ⋯ , 𝑘 i = 1 , 2 , ⋯ , k   满足 𝑥   ≡ 𝑎 𝑖 ( m o d 𝑛 𝑖 ) x ≡ a i ( mod n i )  。
当 𝑖   ≠ 𝑗 i ≠ j   时,有 𝑚 𝑗   ≡ 0 ( m o d 𝑛 𝑖 ) m j ≡ 0 ( mod n i )  ,故 𝑐 𝑗   ≡ 𝑚 𝑗   ≡ 0 ( m o d 𝑛 𝑖 ) c j ≡ m j ≡ 0 ( mod n i )  。又有 𝑐 𝑖   ≡ 𝑚 𝑖   ⋅ ( 𝑚 − 1 𝑖 m o d 𝑛 𝑖 )   ≡ 1 ( m o d 𝑛 𝑖 ) c i ≡ m i ⋅ ( m i − 1 mod n i ) ≡ 1 ( mod n i )  ,所以我们有:
𝑥 ≡ 𝑘 ∑ 𝑗 = 1 𝑎 𝑗 𝑐 𝑗 ( m o d 𝑛 𝑖 ) ≡ 𝑎 𝑖 𝑐 𝑖 ( m o d 𝑛 𝑖 ) ≡ 𝑎 𝑖 ⋅ 𝑚 𝑖 ⋅ ( 𝑚 − 1 𝑖 m o d 𝑛 𝑖 ) ( m o d 𝑛 𝑖 ) ≡ 𝑎 𝑖 ( m o d 𝑛 𝑖 ) x ≡ ∑ j = 1 k a j c j ( mod n i ) ≡ a i c i ( mod n i ) ≡ a i ⋅ m i ⋅ ( m i − 1 mod n i ) ( mod n i ) ≡ a i ( mod n i ) 即对于任意 𝑖   = 1 , 2 , ⋯ , 𝑘 i = 1 , 2 , ⋯ , k  ,上面算法得到的 𝑥 x   总是满足 𝑥   ≡ 𝑎 𝑖 ( m o d 𝑛 𝑖 ) x ≡ a i ( mod n i )  ,即证明了解同余方程组的算法的正确性。
因为我们没有对输入的 𝑎 𝑖 a i   作特殊限制,所以任何一组输入 { 𝑎 𝑖 } { a i }   都对应一个解 𝑥 x  。另外,若 𝑥   ≠ 𝑦 x ≠ y  ,则总存在 𝑖 i   使得 𝑥 x   和 𝑦 y   在模 𝑛 𝑖 n i   下不同余。故系数列表 { 𝑎 𝑖 } { a i }   与解 𝑥 x   之间是一一映射关系,方程组总是有唯一解。
解释 下面演示 CRT 如何解「物不知数」问题。
𝑛   = 3   × 5   × 7   = 1 0 5 n = 3 × 5 × 7 = 105  ;三人同行 七十  希:𝑛 1   = 3 , 𝑚 1   = 𝑛 / 𝑛 1   = 3 5 , 𝑚 − 1 1   ≡ 2 ( m o d 3 ) n 1 = 3 , m 1 = n / n 1 = 35 , m 1 − 1 ≡ 2 ( mod 3 )  ,故 𝑐 1   = 3 5   × 2   = 7 0 c 1 = 35 × 2 = 70  ; 五树梅花 廿一  支:𝑛 2   = 5 , 𝑚 2   = 𝑛 / 𝑛 2   = 2 1 , 𝑚 − 1 2   ≡ 1 ( m o d 5 ) n 2 = 5 , m 2 = n / n 2 = 21 , m 2 − 1 ≡ 1 ( mod 5 )  ,故 𝑐 2   = 2 1   × 1   = 2 1 c 2 = 21 × 1 = 21  ; 七子团圆正 半月 :𝑛 3   = 7 , 𝑚 3   = 𝑛 / 𝑛 3   = 1 5 , 𝑚 − 1 3   ≡ 1 ( m o d 7 ) n 3 = 7 , m 3 = n / n 3 = 15 , m 3 − 1 ≡ 1 ( mod 7 )  ,故 𝑐 3   = 1 5   × 1   = 1 5 c 3 = 15 × 1 = 15  ; 所以方程组的唯一解为 𝑥   ≡ 2   × 7 0   + 3   × 2 1   + 2   × 1 5   ≡ 2 3 3   ≡ 2 3 ( m o d 1 0 5 ) x ≡ 2 × 70 + 3 × 21 + 2 × 15 ≡ 233 ≡ 23 ( mod 105 )  。(除 百零五  便得知) Garner 算法 CRT 的另一个用途是用一组比较小的质数表示一个大的整数。
例如,若 𝑎 a   满足如下线性方程组,且 𝑎   < ∏ 𝑘 𝑖 = 1 𝑝 𝑖 a < ∏ i = 1 k p i  (其中 𝑝 𝑖 p i   为质数):
⎧ { { { ⎨ { { { ⎩ 𝑎 ≡ 𝑎 1 ( m o d 𝑝 1 ) 𝑎 ≡ 𝑎 2 ( m o d 𝑝 2 ) ⋮ 𝑎 ≡ 𝑎 𝑘 ( m o d 𝑝 𝑘 ) { a ≡ a 1 ( mod p 1 ) a ≡ a 2 ( mod p 2 ) ⋮ a ≡ a k ( mod p k ) 我们可以用以下形式的式子(称作 𝑎 a   的混合基数表示)表示 𝑎 a  :
𝑎 = 𝑥 1 + 𝑥 2 𝑝 1 + 𝑥 3 𝑝 1 𝑝 2 + … + 𝑥 𝑘 𝑝 1 … 𝑝 𝑘 − 1 a = x 1 + x 2 p 1 + x 3 p 1 p 2 + … + x k p 1 … p k − 1 Garner 算法  将用来计算系数 𝑥 1 , … , 𝑥 𝑘 x 1 , … , x k  。
令 𝑟 𝑖 𝑗 r i j   为 𝑝 𝑖 p i   在模 𝑝 𝑗 p j   意义下的 逆 :
𝑝 𝑖 ⋅ 𝑟 𝑖 , 𝑗 ≡ 1 ( m o d 𝑝 𝑗 ) p i ⋅ r i , j ≡ 1 ( mod p j ) 把 𝑎 a   代入我们得到的第一个方程:
𝑎 1 ≡ 𝑥 1 ( m o d 𝑝 1 ) a 1 ≡ x 1 ( mod p 1 ) 代入第二个方程得出:
𝑎 2 ≡ 𝑥 1 + 𝑥 2 𝑝 1 ( m o d 𝑝 2 ) a 2 ≡ x 1 + x 2 p 1 ( mod p 2 ) 方程两边减 𝑥 1 x 1  ,除 𝑝 1 p 1   后得
𝑎 2 − 𝑥 1 ≡ 𝑥 2 𝑝 1 ( m o d 𝑝 2 ) ( 𝑎 2 − 𝑥 1 ) 𝑟 1 , 2 ≡ 𝑥 2 ( m o d 𝑝 2 ) 𝑥 2 ≡ ( 𝑎 2 − 𝑥 1 ) 𝑟 1 , 2 ( m o d 𝑝 2 ) a 2 − x 1 ≡ x 2 p 1 ( mod p 2 ) ( a 2 − x 1 ) r 1 , 2 ≡ x 2 ( mod p 2 ) x 2 ≡ ( a 2 − x 1 ) r 1 , 2 ( mod p 2 ) 类似地,我们可以得到:
𝑥 𝑘 = ( … ( ( 𝑎 𝑘 − 𝑥 1 ) 𝑟 1 , 𝑘 − 𝑥 2 ) 𝑟 2 , 𝑘 ) − … ) 𝑟 𝑘 − 1 , 𝑘 m o d 𝑝 𝑘 x k = ( … ( ( a k − x 1 ) r 1 , k − x 2 ) r 2 , k ) − … ) r k − 1 , k mod p k 实现  该算法的时间复杂度为 𝑂 ( 𝑘 2 ) O ( k 2 )  。实际上 Garner 算法并不要求模数为质数,只要求模数两两互质,我们有如下伪代码:
𝐂 𝐡 𝐢 𝐧 𝐞 𝐬 𝐞   𝐑 𝐞 𝐦 𝐚 𝐢 𝐧 𝐝 𝐞 𝐫   𝐀 𝐥 𝐠 𝐨 𝐫 𝐢 𝐭 𝐡 𝐦   c r a  ( 𝐯 , 𝐦 ) : 𝐈 𝐧 𝐩 𝐮 𝐭 :   𝐦 = ( 𝑚 0 , 𝑚 1 , … , 𝑚 𝑛 − 1 ) ,   𝑚 𝑖 ∈ ℤ + ∧ g c d ( 𝑚 𝑖 , 𝑚 𝑗 ) = 1   f o r   a l l   𝑖 ≠ 𝑗 , 𝐯 = ( 𝑣 0 , … , 𝑣 𝑛 − 1 )   w h e r e   𝑣 𝑖 = 𝑥 m o d 𝑚 𝑖 . 𝐎 𝐮 𝐭 𝐩 𝐮 𝐭 :   𝑥 m o d ∏ 𝑛 − 1 𝑖 = 0 𝑚 𝑖 . 1 𝐟 𝐨 𝐫   𝑖   f r o m   1   t o   ( 𝑛 − 1 )   𝐝 𝐨 2 𝐶 𝑖 ← ( ∏ 𝑖 − 1 𝑗 = 0 𝑚 𝑗 ) − 1 m o d 𝑚 𝑖 3 𝑥 ← 𝑣 0 4 𝐟 𝐨 𝐫   𝑖   f r o m   1   t o   ( 𝑛 − 1 )   𝐝 𝐨 5 𝑢 ← ( 𝑣 𝑖 − 𝑥 ) ⋅ 𝐶 𝑖 m o d 𝑚 𝑖 6 𝑥 ← 𝑥 + 𝑢 ∏ 𝑖 − 1 𝑗 = 0 𝑚 𝑗 7 𝐫 𝐞 𝐭 𝐮 𝐫 𝐧   ( 𝑥 ) Chinese Remainder Algorithm  cra  ( v , m ) : Input :  m = ( m 0 , m 1 , … , m n − 1 ) ,  m i ∈ Z + ∧ gcd ( m i , m j ) = 1  for all  i ≠ j , v = ( v 0 , … , v n − 1 )  where  v i = x mod m i . Output :  x mod ∏ i = 0 n − 1 m i . 1 for  i  from  1  to  ( n − 1 )  do 2 C i ← ( ∏ j = 0 i − 1 m j ) − 1 mod m i 3 x ← v 0 4 for  i  from  1  to  ( n − 1 )  do 5 u ← ( v i − x ) ⋅ C i mod m i 6 x ← x + u ∏ j = 0 i − 1 m j 7 return  ( x ) 可以发现在第六行中的计算过程对应上述混合基数的表示。
应用 某些计数问题或数论问题出于加长代码、增加难度、或者是一些其他原因,给出的模数:不是质数 !
但是对其质因数分解会发现它没有平方因子,也就是该模数是由一些不重复的质数相乘得到。
那么我们可以分别对这些模数进行计算,最后用 CRT 合并答案。
下面这道题就是一个不错的例子。
洛谷 P2480 [SDOI2010] 古代猪文   给出 𝐺 , 𝑛 G , n  (1   ≤ 𝐺 , 𝑛   ≤ 1 0 9 1 ≤ G , n ≤ 10 9  ),求:
 𝐺 ∑ 𝑘 ∣ 𝑛 ( 𝑛 𝑘 ) m o d 9 9 9   9 1 1   6 5 9 G ∑ k ∣ n ( n k ) mod 999   911   659 首先,当 𝐺   = 9 9 9   9 1 1   6 5 9 G = 999   911   659   时,所求显然为 0 0  。
否则,根据 欧拉定理 ,可知所求为:
𝐺 ∑ 𝑘 ∣ 𝑛 ( 𝑛 𝑘 ) m o d 9 9 9   9 1 1   6 5 8 m o d 9 9 9   9 1 1   6 5 9 G ∑ k ∣ n ( n k ) mod 999   911   658 mod 999   911   659 现在考虑如何计算:
∑ 𝑘 ∣ 𝑛 ( 𝑛 𝑘 ) m o d 9 9 9   9 1 1   6 5 8 ∑ k ∣ n ( n k ) mod 999   911   658 因为 9 9 9   9 1 1   6 5 8 999   911   658   不是质数,无法保证 ∀ 𝑥   ∈ [ 1 , 9 9 9   9 1 1   6 5 7 ] ∀ x ∈ [ 1 , 999   911   657 ]  ,𝑥 x   都有逆元存在,上面这个式子我们无法直接计算。
注意到 9 9 9   9 1 1   6 5 8   = 2   × 3   × 4 6 7 9   × 3 5 6 1 7 999   911   658 = 2 × 3 × 4679 × 35617  ,其中每个质因子的最高次数均为一,我们可以考虑分别求出 ∑ 𝑘 ∣ 𝑛 ( 𝑛 𝑘 ) ∑ k ∣ n ( n k )   在模 2 2  ,3 3  ,4 6 7 9 4679  ,3 5 6 1 7 35617   这几个质数下的结果,最后用中国剩余定理来合并答案。
也就是说,我们实际上要求下面一个线性方程组的解:
⎧ { { { ⎨ { { { ⎩ 𝑥 ≡ 𝑎 1 ( m o d 2 ) 𝑥 ≡ 𝑎 2 ( m o d 3 ) 𝑥 ≡ 𝑎 3 ( m o d 4 6 7 9 ) 𝑥 ≡ 𝑎 4 ( m o d 3 5 6 1 7 ) { x ≡ a 1 ( mod 2 ) x ≡ a 2 ( mod 3 ) x ≡ a 3 ( mod 4679 ) x ≡ a 4 ( mod 35617 ) 而计算一个组合数对较小的质数取模后的结果,可以利用 卢卡斯定理 。
扩展:模数不互质的情况 两个方程 设两个方程分别是 𝑥   ≡ 𝑎 1 ( m o d 𝑚 1 ) x ≡ a 1 ( mod m 1 )  、𝑥   ≡ 𝑎 2 ( m o d 𝑚 2 ) x ≡ a 2 ( mod m 2 )  ;
将它们转化为不定方程:𝑥   = 𝑚 1 𝑝   + 𝑎 1   = 𝑚 2 𝑞   + 𝑎 2 x = m 1 p + a 1 = m 2 q + a 2  ,其中 𝑝 , 𝑞 p , q   是整数,则有 𝑚 1 𝑝   − 𝑚 2 𝑞   = 𝑎 2   − 𝑎 1 m 1 p − m 2 q = a 2 − a 1  。
由 裴蜀定理 ,当 𝑎 2   − 𝑎 1 a 2 − a 1   不能被 g c d ( 𝑚 1 , 𝑚 2 ) gcd ( m 1 , m 2 )   整除时,无解;
其他情况下,可以通过 扩展欧几里得算法  解出来一组可行解 ( 𝑝 , 𝑞 ) ( p , q )  ;
则原来的两方程组成的模方程组的解为 𝑥   ≡ 𝑏 ( m o d 𝑀 ) x ≡ b ( mod M )  ,其中 𝑏   = 𝑚 1 𝑝   + 𝑎 1 b = m 1 p + a 1  ,𝑀   = l c m ( 𝑚 1 , 𝑚 2 ) M = lcm ( m 1 , m 2 )  。
多个方程 用上面的方法两两合并即可。
习题  本页面最近更新:2025/9/14 21:22:43 ,更新历史  发现错误?想一起完善? 在 GitHub 上编辑此页!  本页面贡献者:Ir1d , StudyingFather , Yanjun-Zhao , Enter-tainer , H-J-Granger , sshwy , Chrogeek , countercurrent-time , NachtgeistW , Xeonacid , Early0v0 , Great-designer , MegaOwIer , 383494 , AngelKitty , CCXXXI , cjsoft , diauweb , ezoixx130 , GekkaSaori , Henry-ZHR , iamtwz , Konano , kzoacn , LovelyBuggies , Makkiy , mgt , minghu6 , P-Y-Y , PotassiumWings , SamZhangQingChuan , stevebraveman , Suyun514 , Tiphereth-A , Unnamed2964 , weiyong1024 , ChungZH , GavinZhengOI , Gesrua , Haohu Shen , HeRaNO , hly1204 , ImpleLee , ksyx , kxccc , little-cindy , lychees , Menci , namasikanam , ouuan , Peanut-Tang , Phemon , renbaoshuo , shawlleyw , SukkaW , xyf007  本页面的全部内容在 CC BY-SA 4.0  和 SATA   协议之条款下提供,附加条款亦可能应用