中国剩余定理与扩展中国剩余定理
中国剩余定理
问题
求解同余方程组
\[\left\{\begin{matrix}
x\equiv a_1(mod\ m_1)\\
x\equiv a_2(mod\ m_2)\\
x\equiv a_3(mod\ m_3)\\
\cdots\\
x\equiv a_n(mod\ m_n)\\
\end{matrix}\right.\]
其中\(m_1,m_2,\cdots,m_n\)为两两互质的整数,求\(x\)的最小的非负整数解。
求解方法
设\(M=\prod_{i=1}^{n}m_i\),也就是所有模数的最小公倍数
\(t_i\)为线性同余方程\(\frac{M}{m_i}t_i\equiv 1(mod\ m_i)\)的最小非负整数解
则\(x=\sum_{i=1}^{n}a_i\frac{M}{m_i}t_i\)是原方程组的一个解
因为\(\forall k\neq i\),\(a_i\frac{M}{m_i}t_i\equiv 0(mod\ m_k)\),而对于\(k==i\),\(a_i\frac{M}{m_i}t_i\equiv a_i(mod\ m_k)\)。所以将\(x=\sum_{i=1}^{n}a_i\frac{M}{m_i}t_i\)代入原方程组,原方程组成立
原方程组的通解\(x+k*M(k\in Z)\)
原方程组的最小非负整数解\((x\% M+M)\% M\)
const int maxn=15;
int n,a[maxn],m[maxn];
int China(){
int M=1,ans=0,x,y;
for(int i=0;i<n;i++) M*=m[i];
for(int i=0;i<n;i++){
int k=M/m[i];
exgcd(k,m[i],x,y);
ans=(ans+a[i]*k*x)%M;
}
return (ans%M+M)%M;
}
```cpp
###扩展中国剩余定理
**问题**
求解同余方程组
$$\left\{\begin{matrix}
x\equiv a_1(mod\ m_1)\\
x\equiv a_2(mod\ m_2)\\
x\equiv a_3(mod\ m_3)\\
\cdots\\
x\equiv a_n(mod\ m_n)\\
\end{matrix}\right.$$
求$x$的最小的非负整数解。
**求解方法**
设方程组的解为$x\equiv a(mod\ M)$
对于方程组
$$\left\{\begin{matrix}
x\equiv a_1(mod\ m_1)\\
x\equiv a_2(mod\ m_2)\\
\end{matrix}\right.$$
将第一个方程化为$x=a_1+m_1*k_1$代入第二个方程,得到$m_1*k_1+m_2*k_2\equiv a_2-a_1$
有解的条件为$gcd(m_1,m_2)\mid (a_2-a_1)$
设$M=lcm(m_1,m_2)=\frac{m1*m2}{gcd(m1,m2)}$
$a=(inv(\frac{m_1}{gcd(m_1,m_2)},\frac{m_2}{gcd(m_1,m_2)})*\frac{(a_2-a_1)}{gcd(m_1,m_2)})\% \frac{m_2}{gcd(m_1.m_2)}*m_1+a_1$
逐个求解所有方程。
**证明**
对于方程组
$$\left\{\begin{matrix}
x\equiv a_1(mod\ m_1)\\
x\equiv a_2(mod\ m_2)\\
\end{matrix}\right.$$
如果$gcd(m_1,m_2)\mid (a_2-a_1)$,则可以转化为求解$k_1,k_2$,使得$\frac{m_1}{gcd(m_1,m_2)}*k_1+\frac{m_2}{gcd(m_1,m_2)}*k_2=\frac{(a_2-a_1)}{gcd(m_1,m_2)}$
也就是$\frac{m_1}{gcd(m_1,m_2)}*k_1\equiv \frac{(a_2-a_1)}{gcd(m_1,m_2)}(mod\ \frac{m_2}{gcd(m_1,m_2)})$
由于此时$gcd(\frac{m_1}{gcd(m_1,m_2)},\frac{m_2}{gcd(m_1,m_2)})=1$,所以
$k_1=inv(\frac{m_1}{gcd(m_1,m_2)},\frac{m_2}{gcd(m_1,m_2)})*\frac{(a_2-a_1)}{gcd(m_1,m_2)}(mod\ \frac{m_2}{gcd(m_1,m_2)})$
$k_1=inv(\frac{m_1}{gcd(m_1,m_2)},\frac{m_2}{gcd(m_1,m_2)})*\frac{(a_2-a_1)}{gcd(m_1,m_2)}+t*\frac{m_2}{gcd(m_1,m_2)}$
将$k_1$代入$x=k_1*m_1+a_1$,得到
$x=inv(\frac{m_1}{gcd(m_1,m_2)},\frac{m_2}{gcd(m_1,m_2)})*\frac{(a_2-a_1)}{gcd(m_1,m_2)}\% \frac{m_2}{gcd(m_1,m_2)}*m_1+a_1(mod\ \frac{m_1*m_2}{gcd(m_1,m_2)})$
所以重新得到了$x\equiv c(mod\ M)$的形式,所以原方程组可以按照这样的方式逐个方程求解。
const int maxn=100010;
int n,a[maxn],m[maxn];
int excrt(){
int c=a[0],M=m[0];
for(int i=1;i<n;i++){
int d=__gcd(M,m[i]);
if((a[i]-c)%d!=0) return -1;
c+=inv(M/d,m[i]/d)((a[i]-c)/d)%(m[i]/d)M;
M=M*m[i]/d;
c=(c%M+M)%M;
}
return (c%M+M)%M;
}
模板题:[hdu1573 X问题](http://acm.hdu.edu.cn/showproblem.php?pid=1573)