您的位置:首页 > 其它

中国剩余定理及扩展

2018-04-10 22:28 253 查看
挂链接

中国剩余定理

设\(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}))\)

就可以了

代码

POJ2891

# 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: