結果
| 問題 |
No.187 中華風 (Hard)
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 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 |
ソースコード
#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;
}
}