中国剩余定理 学习笔记
中国剩余定理
中国剩余定理(Chinese remainder theorem, CRT)可以求解如下形式的同余方程组:
首先构造几个同余方程组 \(\left\{\begin{matrix}x\equiv 1\pmod{a_1}\\x\equiv 0\pmod{a_2}\\\vdots\\x\equiv0\pmod{a_n}\end{matrix}\right.,\left\{\begin{matrix}x\equiv 0\pmod{a_1}\\x\equiv 1\pmod{a_2}\\\vdots\\x\equiv0\pmod{a_n}\end{matrix}\right.,\dots,\left\{\begin{matrix}x\equiv 0\pmod{a_1}\\x\equiv 0\pmod{a_2}\\\vdots\\x\equiv 1\pmod{a_n}\end{matrix}\right.\)
求解这些方程组,以 \(\left\{\begin{matrix}x\equiv 1\pmod{a_1}\\x\equiv 0\pmod{a_2}\\\vdots\\x\equiv0\pmod{a_n}\end{matrix}\right.\) 为例:
设 \(m=\prod_{i=1}^{n}a_i,m_i=\frac{m}{a_i}\)。显然 \(\prod_{i=2}^{n}a_i=\frac{m}{a_1}=m_1\) 满足第一个方程以外的所有方程。求出 \(m_1\) 模 \(a_1\) 的逆元 \(m_1^{-1}\),根据逆元的定义有 \(m_1m_1^{-1}\equiv1\pmod{a_1}\),因此 \(m_1m_1^{-1}\) 为一个解。
将这些方程组分别乘上 \(b_1,b_2\dots b_n\),得到 \(\left\{\begin{matrix}x\equiv b_1\pmod{a_1}\\x\equiv 0\pmod{a_2}\\\vdots\\x\equiv0\pmod{a_n}\end{matrix}\right.,\left\{\begin{matrix}x\equiv 0\pmod{a_1}\\x\equiv b_2\pmod{a_2}\\\vdots\\x\equiv0\pmod{a_n}\end{matrix}\right.,\dots,\left\{\begin{matrix}x\equiv 0\pmod{a_1}\\x\equiv 0\pmod{a_2}\\\vdots\\x\equiv b_n\pmod{a_n}\end{matrix}\right.\) 发现将这些方程组求和,刚好得到原方程,因此求和即为最终的解。
总结一下流程:
-
求 \(m=\prod_{i=1}^{n}a_i\)。
-
求 \(m_i=\frac{m}{a_i}\)。
-
求 \(m_i\) 模 \(a_i\) 的逆元 \(m_i^{-1}\)。
-
对于每一个方程,重复2、3,最终的解为 \(\sum_{i=1}^n b_im_im_i^{-1}\)。
由于最小解不会超过 \(m\),所以要处处对 \(m\) 取模。
template<typename T>T crt(int n,T a[],T b[]){
T m=1,ans=0;
for(int i=1;i<=n;i++)m*=a[i];
for(int i=1;i<=n;i++)ans=(ans+b[i]*(m/a[i])%m*inv(m/a[i],a[i])%m)%m;
return ans;
}
然而在第三步,逆元可能不存在,即 \(a\) 不是两两互质。这时需要扩展中国剩余定理。
扩展中国剩余定理
假如现有两个同余方程 \(x\equiv b_1\pmod{a_1},x\equiv b_2\pmod{a_2}\),等价于 \(x=a_1k_1+b_1=a_2k_2+b_2\)。
移项得到 \(a_1k_1-a_2k_2=b_2-b_1\)。这是一个形如 \(ax+by=c\) 的二元一次方程,可以使用扩展欧几里得算法求解。
首先当 \(\gcd(a_1,a_2)\nmid b_2-b_1\) 时判定无解。否则用扩欧求 \(a_1k_1-a_2k_2=\gcd(a_1,a_2)\) 中 \(k_1\) 的特解 \(x_1\),有 \(k_1=\frac{x_1(b_2-b_1)}{\gcd(a_1,a_2)}\)。对 \(k_1\) 加 \(\frac{a_2}{\gcd(a_1,a_2)}\),\(k_2\) 减 \(\frac{a_1}{\gcd(a_1,a_2)}\) 也是一组解,可以对 \(\frac{a_2}{\gcd(a_1,a_2)}\) 取模。
此时可以求出 \(x\),那么可以将两个同余方程合并成一个新的方程 \(x\equiv b_3\pmod{a_3}\)。其中 \(a_3=\operatorname{lcm}(a_1,a_2), b_3=x\)。整个算法的过程就是不断合并方程,最终成为一个方程,得到的 \(b\) 就是解。
template<typename T>T excrt(int n,T a[],T b[]){
T a1=a[1],b1=b[1];
for(int i=2;i<=n;i++){
T c=b[i]-b1,x,y,d=gcd(a1,a[i]);
exgcd(a1,a[i],x,y);
if(c%d==0)x=(x%(a[i]/d)*(c/d)%(a[i]/d)+a[i]/d)%(a[i]/d),b1+=x*a1,a1*=a[i]/d;
else return -1;
}
return b1;
}
[[数学]]

浙公网安备 33010602011771号