中国剩余定理不互质情况下
参考博客:http://yzmduncan.iteye.com/blog/1323599/
https://www.cnblogs.com/linyujun/p/5199415.html
中国剩余定理不互质的情况下就是相当于把某个表达式通过另外的表达式表达出来
假设我们现有2个表达式
X = a1 (mod m1)
X = a2 (mod m2)
等于 X = a1 + k1 * m1 = a2 + k2 * m2;
然后可以通过移项可以得到 k1 * m1 - k2 * m2 = a2 - a1 (1)
通过拓展欧几里得 我们可以知道 若此方程有整数解 必满足 (a2-a1)%gcd(m1,m2) == 0
(1)式可以变换成 k1*m1 = a2 - a1 (mod m2)
设 d = gcd(m1, m2), c = a2-a1
(m1/d) * k1 = c/d (mod m2/d)
k1 = c/d * inv(m1/d) (mod m2/d)
设 K = c/d * inv(m1/d)
k1 = k + y * (m2/d)
再将k1 带入 X = a1 + k1 * m1 可以得到
X = a1 + k*m1 + y*(m1*m2/d)
即 X = a3 (mod m3) (其中 a3 = a1 + k*m1 m3 = m1*m2/d)
然后通过这个式子对剩下的表达式进行整合 就可以求得最后的答案。
1 #include<cstdio> 2 #define ll long long 3 using namespace std; 4 const int N = 100000+5; 5 ll M[N], A[N];// M->mod A -> 余数 6 ll gcd(ll a, ll b) { 7 return b == 0 ? a : gcd(b, a%b); 8 } 9 void ex_gcd(ll a, ll b, ll &x, ll &y, ll &d) 10 { 11 if(b == 0) { 12 x = 1, y = 0, d = a; 13 return ; 14 } 15 ex_gcd(b, a%b, y, x, d); 16 y -= a/b*x; 17 return ; 18 } 19 ll inv(ll n, ll p) { 20 ll x, y, d; 21 ex_gcd(n, p, x, y, d); 22 return (d == 1) ? (x % p + p) % p : -1; 23 } 24 ll china_(ll A[], ll M[], ll n) 25 { 26 ll x = A[0], m = M[0]; 27 for(int i = 1; i < n; i++) { 28 ll c = A[i] - x, d = gcd(M[i], m); 29 if(c % d) return -1; 30 ll k = c/d * inv(m/d, M[i]/d)%(M[i]/d); 31 x += m*k; 32 m *= M[i]/d; 33 } 34 return (x%m+m)%m; 35 } 36 int main() 37 { 38 int n; 39 while(~scanf("%d", &n)) { 40 for(int i = 0; i < n; i++) 41 scanf("%lld%lld", &M[i], &A[i]); 42 ll ans = china_(A, M, n); 43 printf("%lld", ans); 44 } 45 return 0; 46 }