大意不再赘述。
思路:
线性同余方程的应用。
令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; }