求解线性同余方程组,模数可能不两两互质,因此需要使用合并线性同余方程的方法。
#include <stdio.h>
typedef long long int llt;
//The extended Euclidean algorithm implemented by iteration
//returns gcd(a,b), and x, y are satisfied with ax + by = gcd
llt exEuclid(llt a,llt b,llt&x,llt&y){
llt x0 = 1, y0 = 0;
llt x1 = 0, y1 = 1;
x = 0; y = 1;
llt r = a % b;
llt q = ( a - r ) / b;
while( r ){
x = x0 - q * x1;
y = y0 - q * y1;
x0 = x1; y0 = y1;
x1 = x; y1 = y;
a = b; b = r; r = a % b;
q = ( a - r ) / b;
}
return b;
}
//to convert two congruence equations to equivalent one
//x = r1 (mod m1)
//x = r2 (mod m2)
//the out put is: x = r3 (mod m3)
//return true if there is a solution, otherwise false
bool mergeCrt(llt r1,llt m1,llt r2,llt m2,llt&r3,llt&m3){
llt x,y;
llt g = exEuclid(m1,m2,x,y);
llt r = (r2 - r1) % m2;
if ( r < 0 ) r += m2;
if ( r % g ) return false;//no solution
x = r / g * x % ( m2 / g );//the least positive solution
m3 = m1 / g * m2; //lcm
r3 = ( ( x * m1 ) % m3 + r1 ) % m3;
return true;
}
int main(){
int n;
while ( EOF != scanf("%d",&n) ){
llt m1=1,r1=0,m2,r2;
bool flag = true;
for(int i=0;i<n;++i){
scanf("%lld%lld",&m2,&r2);
if ( flag ){
flag = mergeCrt(r1,m1,r2,m2,r1,m1);
}
}
r1 %= m1;
if ( r1 < 0 ) r1 += m1;
printf("%lld\n",flag?r1:-1LL);
}
return 0;
}