P4777 【模板】扩展中国剩余定理(EXCRT)

题目链接:https://www.luogu.com.cn/problem/P4777

解题思路:完全来自 oi.wiki

注意:中间过程有一步可能会超 long long,得开 int128(代码第 \(39\) 行,因为这里有三个数相乘了)

示例程序:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

ll exgcd(ll a, ll b, ll &x, ll &y) {
    if (!b) {
        x = 1;
        y = 0;
        return a;
    }
    ll d = exgcd(b, a%b, x, y);
    ll t = x;
    x = y;
    y = t - a / b * y;
    return d;
}

ll gcd(ll a, ll b) {
    return b ? gcd(b, a%b) : a;
}

ll lcm(ll a, ll b) {
    return a / gcd(a, b) * b;
}

ll excrt(vector<pair<ll, ll>> crts) {
    ll m1 = 1, r1 = 0;
    for (auto &[m2, r2] : crts) {
        if (m1 == m2) {
            if (r1 != r2) return -1;
            continue;
        }
        ll p, q;
        ll d = exgcd(m1, -m2, p, q);
        if ((r2 - r1) % d) {
            return -1;
        }
        ll M = lcm(m1, m2);
        __int128 R = (__int128) m1 * p * ((r2-r1)/d) + r1;
        m1 = M;
        r1 = (R % M + M) % M;
    }
    return r1;
}

int main() {
    int n;
    scanf("%d", &n);
    vector<pair<ll, ll>> crts(n);
    for (int i = 0; i < n; i++)
        scanf("%lld%lld", &crts[i].first, &crts[i].second);
    ll ans = excrt(crts);
    printf("%lld\n", ans);
    return 0;
}
posted @ 2026-05-25 11:00  quanjun  阅读(3)  评论(0)    收藏  举报