现在,m1,m2,…mn之间没有任何关系。
只考虑两个怎么处理?
可以得到:x=a1+k1∗m1;x=a2+k2∗m2
所以 a1+k1∗m1=a2+k2∗m2
k2∗m2−k1∗m1=a1−a2;
很像:a×x+b×y=c
设m1,m2 的gcd 为 g
设a1−a2=c
当c不是g的倍数的时候,那就完了。(exgcd无解情况)
如果是,就用exgcd求出k2×m2+k1×m1=gcd(m1,m2)的k1
因为c是g的倍数,所以,两边同时乘上c/g,即k1乘上c/g
就得到了k2×m2+k1×m1=c的解k1。
当然,最好k1 再模一下m2 (k1,k2做出调整),防止爆longlong
然后可以反推x,
但是注意,我们列的原方程是:k2×m2−k1×m1=c
差一个符号,所以k1 实际上是 −k1
x=−k1×m1+a1;
这样就求出了x。(可以把这个x0转化成最小的非负数解)
这个x符合第一个方程,也符合第二个方程。设这个x为x0
所以,可以得到通解是:x=x0+k×lcm(m1,m2)
满足这个条件的x就满足第一第二两个方程。满足第一第二两个方程的所有的解也都是这个方程的解。
所以第一第二个方程和这个方程是等价的。
将这个方程转化一下,可以得到新的同余方程:x=x0(modlcm(m1,m2))
这样,我们成功的把两个方程转化成了一个方程,以此类推。
最后留下的这个方程,它的x_0的最小非负数解,就是我们要的最终答案!!!!!!!!!!!!!!
ll ai[maxn], bi[maxn], n;
ll mul(ll a, ll b, ll mod){
ll res = 0;
while(b > 0){
if(b & 1) res = (res + a) % mod;
a = (a + a) % mod;
b >>= 1;
}
return res;
}
ll exgcd(ll a, ll b, ll &x, ll &y){
if(b == 0){x = 1; y = 0; return a;}
ll gcd = exgcd(b, a % b, x, y);
ll tp = x;
x = y; y = tp - a / b * y;
return gcd;
}
ll excrt(){
ll x, y, k;
ll M = bi[1], ans = ai[1];//第一个方程的解特判
for(int i = 2; i <= n; i++){
ll a = M, b = bi[i], c = (ai[i] - ans % b + b) % b;//ax≡c(mod b)
ll gcd = exgcd(a, b, x, y), bg = b / gcd;
if(c % gcd != 0) return -1; //判断是否无解,然而这题其实不用
x = mul(x, c / gcd, bg);//把x转化为最小非负整数解
ans += x * M;//更新前k个方程组的答案
M *= bg;
ans = (ans % M + M) % M;
}
return (ans % M + M) % M;
}
int main(){
scanf("%lld", &n);
for(int i = 1; i <= n; ++i)
scanf("%lld%lld", &bi[i], &ai[i]);
printf("%lld",excrt());
return 0;
}