namespace EXCRT { using T = int64_t; T abs(T a){ return a < 0 ? -a : a; } T mod_mul(T a, T b, T mod){ T res = 0; for (; b; b >>= 1, (a += a) %= mod) if (b & 1) (res += a) %= mod; return res; } T gcd(T a, T b){ return b == 0 ? a : gcd(b, a % b); } T exgcd(T a, T b, T &x, T &y){ if (b == 0) { x = 1; y = 0; return a; } T res = exgcd(b, a % b, y, x); y -= a / b * x; return res; }
boolsolve_2equ(T b1, T b2, T m1, T m2, T &x, T &M){ ((b1 %= m1) += m1) %= m1; ((b2 %= m2) += m2) %= m2; T g = gcd(m1, m2), r = b2 - b1; M = m1 / g * m2; if (abs(r) % g) returnfalse; T k1, k2; exgcd(m1, m2, k1, k2); if (r < 0) k1 = -k1; ((k1 %= M) += M) %= M; k1 = mod_mul(k1, abs(r) / g, M); x = ((mod_mul(k1, m1, M) + b1) % M + M) % M; returntrue; }
boolexcrt(T b[], T m[], constint len, T &res){ T pre_b = b[1], pre_m = m[1]; T now_b, now_m; for (int i = 2; i <= len; ++i) { now_b = b[i]; now_m = m[i]; if (!solve_2equ(pre_b, now_b, pre_m, now_m, pre_b, pre_m)) returnfalse; } res = pre_b; returntrue; } } // namespace EXCRT using EXCRT::excrt;