1. 程式人生 > 實用技巧 >中國剩餘定理基本講解

中國剩餘定理基本講解

「物不知數」問題

有物不知其數,三三數之剩二,五五數之剩三,七七數之剩二。問物幾何?

即求滿足以下條件的整數:除以 \(3\)\(2\) ,除以 \(5\)\(3\) ,除以 \(7\)\(2\)

該問題最早見於《孫子算經》中,並有該問題的具體解法。宋朝數學家秦九韶於 1247 年《數書九章》卷一、二《大衍類》對「物不知數」問題做出了完整系統的解答。上面具體問題的解答口訣由明朝數學家程大位在《演算法統宗》中給出:

三人同行七十希,五樹梅花廿一支,七子團圓正半月,除百零五便得知。

\(2\times 70+3\times 21+2\times 15=233=2\times 105+23\)

,故答案為 \(23\)

演算法簡介及過程

中國剩餘定理 (Chinese Remainder Theorem, CRT) 可求解如下形式的一元線性同餘方程組(其中 \(n_1, n_2, \cdots, n_k\) 兩兩互質):

\[\left \{ \begin{array}{ccc} x &\equiv& a_1 \pmod {n_1} \\ x &\equiv& a_2 \pmod {n_2} \\ &\vdots& \\ x &\equiv& a_k \pmod {n_k} \\ \end{array} \right. \]

上面的「物不知數」問題就是一元線性同餘方程組的一個例項。

演算法流程

  1. 計算所有模數的積 \(n\)
  2. 對於第 \(i\) 個方程:
    1. 計算 \(m_i=\frac{n}{n_i}\)
    2. 計算 \(m_i\) 在模 \(n_i\) 意義下的 逆元 \(m_i^{-1}\)
    3. 計算 \(c_i=m_im_i^{-1}\)不要對 \(n_i\) 取模 )。
  3. 方程組的唯一解為: \(a=\sum_{i=1}^k a_ic_i \pmod n\)

虛擬碼

1 → n
0 → ans
for i = 1 to k
	n * n[i] → n
for i = 1 to k
	n / n[i] → m
	inv(m, n[i]) → b               // b * m mod n[i] = 1
	(ans + a[i] * m * b) mod n → ans
return ans

演算法的證明

我們需要證明上面演算法計算所得的 \(a\) 對於任意 \(i=1,2,\cdots,k\) 滿足 \(a\equiv a_i \pmod {n_i}\)

\(i\neq j\) 時,有 \(m_j\equiv 0 \pmod {n_i}\) ,故 \(c_j\equiv m_j\equiv 0 \pmod {n_i}\) 。又有 \(c_i\equiv m_i(m_i^{-1}\bmod {n_i})\equiv 1 \pmod {n_i}\) ,所以我們有:

\[\begin{aligned} a&\equiv \sum_{j=1}^k a_jc_j &\pmod {n_i} \\ &\equiv a_ic_i &\pmod {n_i} \\ &\equiv a_im_i(m^{-1}_i \bmod n_i) &\pmod {n_i} \\ &\equiv a_i &\pmod {n_i} \end{aligned} \]

即對於任意 \(i=1,2,\cdots,k\) ,上面演算法得到的 \(a\) 總是滿足 \(a\equiv a_i \pmod{n_i}\) ,即證明了解同餘方程組的演算法的正確性。

因為我們沒有對輸入的 \(a_i\) 作特殊限制,所以任何一組輸入 \(\{a_i\}\) 都對應一個解 \(a\)

另外,若 \(x\neq y\) ,則總存在 \(i\) 使得 \(x\)\(y\) 在模 \(n_i\) 下不同餘。

故係數列表 \(\{a_i\}\) 與解 \(a\) 之間是一一對映關係,方程組總是有唯一解。

下面演示 CRT 如何解「物不知數」問題。

  1. \(n=3\times 5\times 7=105\)
  2. 三人同行 七十 希: \(n_1=3, m_1=n/n_1=35, m_1^{-1}\equiv 2\pmod 3\) ,故 \(c_1=35\times 2=70\)
  3. 五樹梅花 廿一 支: \(n_2=5, m_2=n/n_2=21, m_2^{-1}\equiv 1\pmod 5\) ,故 \(c_2=21\times 1=21\)
  4. 七子團圓正 半月\(n_3=7, m_3=n/n_3=15, m_3^{-1}\equiv 1\pmod 7\) ,故 \(c_3=15\times 1=15\)
  5. 所以方程組的唯一解為 \(a\equiv 2\times 70+3\times 21+2\times 15\equiv 233\equiv 23 \pmod {105}\) 。(除 百零五 便得知)

應用

某些計數問題或數論問題出於加長程式碼、增加難度、或者是一些其他不可告人的原因,給出的模數: 不是質數

但是對其質因數分解會發現它沒有平方因子,也就是該模數是由一些不重複的質數相乘得到。

那麼我們可以分別對這些模數進行計算,最後用 CRT 合併答案。

推薦練習:BZOJ 1951

比較兩 CRT 下整數

考慮 CRT, 不妨假設 \(n_1\leq n_2 \leq ... \leq n_k\)

\[\left\{ \begin{array} { r l } { x } & { \equiv a _ { 1 } \left( \bmod n _ { 1 } \right) } \\ { x } & { \equiv a _ { 2 } \left( \bmod n _ { 2 } \right) } \\ { } & { \vdots } \\ { x } & { \equiv a _ { k } \left( \bmod n _ { k } \right) } \end{array} \right. \]

與 PMR(Primorial Mixed Radix) 表示

\(x=b_1+b_2n_1+b_3n_1n_2...+b_kn_1n_2...n_{k-1} ,b_i\in [0,n_i)\)

將數字轉化到 PMR 下,逐位比較即可

轉化方法考慮依次對 PMR 取模

\[\begin{aligned} b_1&=a_1 \bmod n_1\\ b_2&=(a_2-b_1)c_{1,2} \bmod n_2\\ b_3&=((a_3-b_1')c_{1,3}-x_2')c_{2,3} \bmod n_3\\ &...\\ b_k&=(...((a_k-b_1)c_{1,k}-b_2)c_{2,k})-...)c_{k-1,k} \bmod n_k \end{aligned} \]

其中 \(c_{i,j}\) 表示 \(n_i\)\(n_j\) 的逆元, \(c_{i,j}n_i \equiv 1 \pmod {n_j}\)

擴充套件:模數不互質的情況

兩個方程

設兩個方程分別是 \(x\equiv a_1 \pmod {m_1}\)\(x\equiv a_2 \pmod {m_2}\)

將它們轉化為不定方程: \(x=m_1p+a_1=m_2q+a_2\) ,其中 \(p, q\) 是整數,則有 \(m_1p-m_2q=a_2-a_1\)

由裴蜀定理,當 \(a_2-a_1\) 不能被 \(\gcd(m_1,m_2)\) 整除時,無解;

其他情況下,可以通過擴充套件歐幾里得演算法解出來一組可行解 \((p, q)\)

則原來的兩方程組成的模方程組的解為 \(x\equiv b\pmod M\) ,其中 \(b=m_1p+a_1\)\(M=\text{lcm}(m_1, m_2)\)

多個方程

用上面的方法兩兩合併就可以了……

推薦練習:POJ 2891

【模板】擴充套件中國剩餘定理

「NOI2018」屠龍勇士

「TJOI2009」猜數字

「SDOI2010」古代豬文

李永樂老師視訊講解