中国剩余定理用于求解 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;
}