中国剩余定理及扩展
中国剩余定理
设\(m_1, m_2, ..., m_k\)两两互质
则对于方程组
\(x\equiv a_1 (mod\ m_1)\)
\(x\equiv a_2 (mod\ m_2)\)
\(...\)
\(x\equiv a_k (mod\ m_k)\)
有整数解
并且在模\(M=\Pi m_i\)的意义下解唯一
为\(\sum(a_i*M/m_i)(mod\ M)\)
\(Exgcd\)一波求解就好了
证明:
对于方程组
\(x\equiv 0 (mod\ m_1)\)
\(x\equiv 0 (mod\ m_2)\)
\(...\)
\(x\equiv 1 (mod\ m_i)\)
\(...\)
\(x\equiv 0 (mod\ m_k)\)
就等价于求解
\((M/m_i)x\equiv 1(mod\ m_i)\)
而如果\(x\equiv c(mod\ m_i)\)
那么\(a*x\equiv a*c(mod\ m_i)\)
扩展
求解模数不互质情况下的线性方程组
考虑合并两个方程组
\(x\equiv a_i (mod\ m_i)\)
\(x\equiv a_{i+1} (mod\ m_{i+1})\)
写成
\(x=a_i+x_1*m_i=a_{i+1}+x_2*m_{i+1}\)
的形式
求\(x\)最小,那么可以先解出\(x_1\)最小的解\(x'\),带入就是
直接\(Exgcd\)求解\(x_1*m_i+x_2*m_{i+1}=a_{i+1}-a_i\),就好了
合并之后
显然新的方程就是
\(x\equiv x' (mod\ lcm(m_i, m_{i+1}))\)
就可以了
代码
# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
template <class Int>
IL void Input(RG Int &x){
RG int z = 1; RG char c = getchar(); x = 0;
for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
x *= z;
}
IL ll ExGcd(RG ll a, RG ll b, RG ll &x, RG ll &y){
if(!b){
x = 1, y = 0;
return a;
}
RG ll d = ExGcd(b, a % b, y, x);
y -= a / b * x;
return d;
}
const int maxn(1e5 + 5);
int n, flg;
ll ans, x, y, m[maxn], b[maxn];
int main(RG int argc, RG char* argv[]){
while(scanf("%d", &n) != EOF){
ans = flg = 0;
for(RG int i = 1; i <= n; ++i) Input(m[i]), Input(b[i]);
for(RG int i = 2; i <= n; ++i){
RG ll d = ExGcd(m[1], m[i], x, y), g = b[i] - b[1], t;
if(g % d){
flg = 1;
break;
}
x *= g / d, t = m[i] / d, x = (x % t + t) % t;
b[1] += m[1] * x, m[1] *= t, b[1] %= m[1];
}
if(flg) puts("-1");
else printf("%lld\n", (b[1] % m[1] + m[1]) % m[1]);
}
return 0;
}