假设有如下方程:
合并可得:
然后利用扩展欧几里得算法, 算出x1的最小正整数解, 代入原方程即可得y的值, 然后求出最终答案
struct P {
ll as, lc; ///as为ai, lc为最小公倍数
P() {}
P(ll as, ll lc) : as(as), lc(lc) {}
};
ll exgcd(ll a, ll b, ll &x, ll &y) {
if(b == 0) {
x = 1; y = 0;
return a;
}
ll ans = exgcd(b, a % b, x, y);
ll t = x;
x = y;
y = t - a / b * y;
return ans;
}
ll inv(ll t, ll p) {
ll d, x, y;
d = exgcd(t, p, x, y);
return (x % p + p) % p;
}
P Merge(P gg, P rr) {
if(gg.as == -1 || rr.as == -1) return P(-1, -1);
ll a1 = gg.as, b1 = gg.lc;
ll a2 = rr.as, b2 = rr.lc;
ll kx, ky;
ll g = exgcd(b1, b2, kx, ky);
if((a2 - a1) % g) return P(-1, -1);
ll p = ((a2 - a1) % b2 + b2) % b2;
p /= g;
p *= inv(b1 / g, b2 / g);
p %= b2;
p *= b1;
p += a1;
ll b3 = b1 / g * b2;
ll a3 = (p % b3 + b3) % b3;
return P(a3, b3);
}
ll CRT(ll *a, ll *m, int n) {
P g(a[1], m[1]);
for(int i = 1; i < n; i++) {
g = Merge(g, P(a[i], m[i]));
if(g.as == -1) return g;
}
return g;
}