using Num_t = long long;
static_assert(std::is_signed_v<Num_t>);
std::pair<Num_t, Num_t> extendedEuclid(Num_t a, Num_t b) {
Num_t ua = 1; Num_t va = 0;
Num_t ub = 0; Num_t vb = 1;
while (b != 0) {
Num_t t = a / b;
a -= t * b;
ua -= t * ub;
va -= t * vb;
std::swap(a, b);
std::swap(ua, ub);
std::swap(va, vb);
}
if (a < 0) {
ua = -ua;
va = -va;
}
return {ua, va};
}
std::pair<Num_t, Num_t> crt(Num_t x0, Num_t m0, Num_t x1, Num_t m1) { /* m0 * m1 < std::numeric_limits<Num_t>::max() / 2 */
assert(m0 > 0 && m1 > 0);
if (m0 < m1) {
std::swap(x0, x1);
std::swap(m0, m1);
}
x0 %= m0; x1 %= m1;
auto [t0, t1] = extendedEuclid(m0, m1);
Num_t g = t0 * m0 + t1 * m1;
if ((x1 - x0) % g != 0) {
return {-1, -1};
}
Num_t resm = m0 * m1 / g;
Num_t res = x0 + t0 * ((x1 - x0) / g) % m1 * m0;
res = (res % resm + resm) % resm;
return {res, resm};
}
template <typename... Num_ts>
std::pair<Num_t, Num_t> crt(Num_t x0, Num_t m0, Num_t x1, Num_t m1, Num_ts... args) {
auto [x, m] = crt(x0, m0, x1, m1);
if (x == -1) {
return {-1, -1};
}
return crt(x, m, args...);
}