大意不再赘述。
思路:
线性同余方程的应用。
令m = lcm(m1, m2);
x ≡ b1 (mod m1)
x ≡ b2 (mod m2)
以上等价于 x = b1 + m1y1; x = b2 + m2y2;
联立可得:
b1 + m1y1 = b2 + m2y2,即m1y1 - m2y2 = b2-b1;
易知此方程的解为y2,因此小于m的非负整数解即为(b2 + m2y2) % m
迭代的时候注意,余数要变为b1 = m1*x0 + b1; m1 = (m1*m2);
为什么可以这样?
x ≡ b1 (mod m1)
x ≡ b2 (mod m2)
令m = lcm(m1, m2);
设m = z1 * m1 = z2 * m2;
x = b1 + m1*y1; (1)
x = b2 + m2*y2; (2)
x' = m*y3 + x; (3)
把(1)带入(3),得 x' = b1 + m1*y1 + z1*m1*y3 = b1 + (y1+z1*y3)*b1,符合要求。
所以两个式子合并后的结果就是:
x' ≡ x (mod m),其中m = lcm(m1, m2);
一直迭代下去,就可以得到结果。
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
LL n;
void ex_gcd(LL a, LL b, LL &d, LL &x, LL &y)
{
if(!b)
{
d = a; x = 1; y = 0;
}
else
{
ex_gcd(b, a%b, d, y, x);
y -= x*(a/b);
}
}
LL solve()
{
LL a, b, d, x, y;
LL a1, r1, a2, r2;
scanf("%lld%lld", &a1, &r1);
int f = 0;
for(int i = 1; i < n; i++)
{
scanf("%lld%lld", &a2, &r2);
a = a1, b = a2;
ex_gcd(a, b, d, x, y);
if((r2-r1) % d) f = 1;
int b1 = b / d;
x *= (r2-r1) / d;
x = (x%b1+b1) % b1;
r1 = a1*x + r1;
a1 = a1*(a2/d);
}
return f ? -1 : r1;
}
int main()
{
while(~scanf("%lld", &n))
{
printf("%lld\n", solve());
}
return 0;
}