中国剩余定理用于求解 x≡ai(mod mi),其中mi两两互质,x有唯一解。
令M为mi的乘积,wi = M/mi,wi关于模mi的逆元为pi,即满足wi*pi + mi*qi = 1.
则上述方程组等价于 x≡ w1*p1*a1 + w2*p2*a2 +......+wk*pk*ak(mod M)................................................................①
验证: 当M = m1时, (w2*p2*a2 +......+wk*pk*ak)%m1 = 0,那么上式变为 x≡w1*p1*a1(mod m1),又因为w1的关于模m1的逆元是p1,那么进一步化简为x≡a1(mod m1)。类比当M = m2,m3,,,,mk时,①式都是成立的。
因此求x,只需求w1*p1*a1 + w2*p2*a2 +......+wk*pk*ak(mod M),其中wi,ai是已知的,pi可根据方程wi*pi + mi * qi = 1用扩展欧几里得求出。
#include <stdio.h> #include <map> #include <set> #include <stack> #include <queue> #include <vector> #include <cmath> #include <stdio.h> #include <stdlib.h> #include <cstring> #include <iostream> #include <limits.h> #include <algorithm> #define LL long long #define _LL __int64 using namespace std; LL extend_gcd(LL a, LL b, LL &x, LL &y) { if(b == 0) { x = 1; y = 0; return a; } LL d = extend_gcd(b,a%b,x,y); LL t = x; x = y; y = t - a/b*y; return d; } LL CRT(LL *p, LL *o, int num) { LL x,y; LL ans = 0,n = 1; for(int i = 0; i < num; i++) n *= o[i]; for(int i = 0; i < num; i++) { extend_gcd(n/o[i],o[i],x,y); x = (x + o[i])%o[i]; ans = (ans + n/o[i]*x*p[i])%n; } return ans; } int main() { int n; LL a[15],m[15]; while(~scanf("%d",&n)) { for(int i = 0; i < n; i++) scanf("%lld %lld",&a[i],&m[i]); printf("%lld\n",CRT(a,m,n)); } return 0; }