这个题不能直接应用中国剩余定理,因为m的值可能不互素。。。。所以用两两求解的方法来求解(应该是叫迭代吧。。。自己是这么跟别人说的。。。)看下面的例子。。
x = 1 (mod 5)
x = 2 (mod 6)
x = 3 (mod 7)
首先我们把第一个方程写成 x = 5*t+1 ,然后带入第二个方程,得5*t + 1 = 2(mod 6) ==> t = 5(mod 6) ;再写成 t = 6*u+5
则 x = 5*(6*u+5)+1 = 30 *u +26; 再次带入第三个方程,30 *u +26=3(mod 7) 可以得出 u=6(mod 7);
则 u = 7*v+6 ; x = 30*(7*v + 6)+26=210*v+206;
所以 x = 206(mod 207);
就按照这样不断更新 a*x=b(mod n) 中的a 和 n ,逐次带入来求解。。。。。
#include <iostream> using namespace std; #define LL long long LL ex_gcd(LL a, LL b, LL &x, LL &y) { if (b == 0) { x = 1, y = 0; return a; } LL d = ex_gcd(b, a % b, x, y); LL t = x; x = y; y = t - a / b*y; return d; } LL mod(LL a,LL b,LL n,LL &d){ // a*x=b(mod n) ,d 是返回a, n的最大公约数 LL e,x,y; d=ex_gcd(a,n,x,y); if(b%d!=0) return -1; e=(x*(b/d))%n; while(e<0) e+=n/d; // a,n 可能不互素 所以加n/d 可以得到最小正整数解 return e; } int main(int argc, char** argv) { bool flag; LL m,a1,m1,a2,m2,x,d; while(scanf("%lld",&m)!=-1){ scanf("%lld%lld",&m1,&a1); flag=0; for(int i=1;i<m;i++){ scanf("%lld%lld",&m2,&a2); if(flag) continue; x=mod(m1,a2-a1,m2,d); if(x==-1){ flag=1; continue; } a1+=m1*x; m1=m1*m2/d; a1=(a1%m1+m1)%m1; } if(flag) printf("-1\n"); else printf("%lld\n",a1); } return 0; }