結果

問題 No.187 中華風 (Hard)
ユーザー ooaiu
提出日時 2025-06-07 04:50:34
言語 C++23
(gcc 13.3.0 + boost 1.87.0)
結果
AC  
実行時間 288 ms / 3,000 ms
コード長 5,293 bytes
コンパイル時間 3,357 ms
コンパイル使用メモリ 279,076 KB
実行使用メモリ 7,844 KB
最終ジャッジ日時 2025-06-07 04:50:44
合計ジャッジ時間 8,238 ms
ジャッジサーバーID
(参考情報)
judge2 / judge3
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other AC * 25
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>
using ll = long long;
using u8 = uint8_t;
using i32 = int32_t;
using u32 = uint32_t;
using i64 = int64_t;
using u64 = uint64_t;
using i128 = __int128_t;
using u128 = __uint128_t;

namespace internal {

constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

constexpr long long pow_mod_constexpr(long long x, long long n, int m_) {
    if (m_ == 1) return 0;
    unsigned int m = static_cast<unsigned int>(m_);
    unsigned long long r = 1, y = safe_mod(x, m);
    while (n) {
        if (n & 1) {
            r = (r * y) % m;
        }
        y = (y * y) % m;
        n >>= 1;
    }
    return r;
}

constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long t = n - 1;
    while (t % 2 == 0) t /= 2;
    constexpr long long base[3] = {2, 7, 61};
    for (long long a : base) {
        long long d = t;
        long long v = pow_mod_constexpr(a, t, n);
        if (v == 1) continue;
        while (d != n - 1 && v != n - 1) {
            v = v * v % n;
            d <<= 1;
        }
        if (v != n - 1 && d % 2 == 0) return false;
    }
    return true;
}
template <int n>
constexpr bool is_prime = is_prime_constexpr(n);

constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;

        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

constexpr long long inv_mod(long long x, long long m) {
    assert(1 <= m);
    auto z = inv_gcd(x, m);
    assert(z.first == 1);
    return z.second;
}

constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; i <= x / i; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) x /= i;
        }
    }
    if (x > 1) divs[cnt++] = x;
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m>
constexpr int primitive_root = primitive_root_constexpr(m);

unsigned long long floor_sum_unsigned(unsigned long long n,
                                      unsigned long long m,
                                      unsigned long long a,
                                      unsigned long long b) {
    unsigned long long ans = 0;
    while (true) {
        if (a >= m) {
            ans += n * (n - 1) / 2 * (a / m);
            a %= m;
        }
        if (b >= m) {
            ans += n * (b / m);
            b %= m;
        }

        unsigned long long y_max = a * n + b;
        if (y_max < m) break;
        n = (unsigned long long)(y_max / m);
        b = (unsigned long long)(y_max % m);
        std::swap(m, a);
    }
    return ans;
}

}  // namespace internal

template <class T>
bool Prepare_Garner(std::vector<T>& a, std::vector<T>& p) {
    int n = a.size();

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < i; j++) {
            T g = std::gcd(p[i], p[j]);
            if ((a[j] - a[i]) % g != 0)
                return false;

            p[i] /= g, p[j] /= g;
            T gi = std::gcd(p[i], g);
            T gj = g / gi;

            do {
                int g = std::gcd(gi, gj);
                gi *= g, gj /= g;
            } while (std::gcd(gi, gj) != 1);

            p[i] *= gi, p[j] *= gj;

            a[i] %= p[i], a[j] %= p[j];
        }
    }
    return true;
}

template <class U>
std::vector<U> Garner(const std::vector<U>& a, const std::vector<U>& p) {
    assert(a.size() == p.size());
    std::vector<U> x(a.size());
    int n = a.size();

    for (int i = 0; i < n; i++) {
        x[i] = a[i];
        for (int j = 0; j < i; j++) {
            long long z = internal::inv_mod(p[j], p[i]) * (x[i] - x[j]);
            z = internal::safe_mod(z, p[i]);
            x[i] = z;
        }
    }
    return x;
}

int main() {
    int N;
    std::cin >> N;
    using namespace std;
    vector<long long> X(N), Y(N);
    for(int i = 0; i < N; i++) cin >> X[i] >> Y[i];
    if (!Prepare_Garner(X, Y)) {
        cout << -1 << "\n";
        return 0;
    }

    const int MOD = (int)1e9 + 7;
    auto T = Garner(X, Y);
    if (T == vector<long long>(T.size())) {
        ll ans = 1;
        for (int i = 0; i < T.size(); i++) ans = (ans * Y[i]) % MOD;
        cout << ans << endl;
    } else {
        ll prod = 1;
        ll ans = 0;
        for (int i = 0; i < T.size(); i++) {
            ans += T[i] * prod;
            prod *= Y[i];
            ans %= MOD;
            prod %= MOD;
        }
        cout << ans << endl;
    }
}
0