結果
| 問題 |
No.187 中華風 (Hard)
|
| コンテスト | |
| ユーザー |
東前頭十一枚目
|
| 提出日時 | 2019-09-26 16:55:50 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 3,210 bytes |
| コンパイル時間 | 1,752 ms |
| コンパイル使用メモリ | 171,764 KB |
| 実行使用メモリ | 6,944 KB |
| 最終ジャッジ日時 | 2024-09-23 08:00:49 |
| 合計ジャッジ時間 | 7,341 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 23 WA * 2 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
template<typename T>
struct ChineseRemainderTheorem {
inline T modulo(T x, T mod) {
if(0 <= x and x < mod) return x;
x %= mod;
if(x < 0) x += mod;
return x;
}
// gcd(a, b)
T exGCD(T a, T b) {
T _p, _q;
return exGCD(a, b, _p, _q);
}
// gcd(a, b)
// ap + bq = gcd(a, b)を満たす(p, q)
T exGCD(T a, T b, T &p, T &q) {
if(b == 0) {
// gcd(a, b)p + 0q = gcd(a, b)
p = 1, q = 0;
return a;
}
T ret = exGCD(b, a % b, q, p);
q -= a / b * p;
return ret;
}
// Garnerの前処理(互いに素にする)
void normalisation(vector<T> &b, vector<T> &mod) {
for(int i = 0; i < (int)b.size(); ++i) {
for(int j = 0; j < i; ++j) {
T g = exGCD(mod[i], mod[j]);
// 必要十分性の確認
if ((b[i] - b[j]) % g != 0) throw "NOT FOUND";
mod[i] /= g;
mod[j] /= g;
T gi = exGCD(mod[i], g);
T gj = g / gi;
// 共通する場合,iの方が指数大
while(true) {
T gg = exGCD(gi, gj);
if(gg == 1) break;
gi *= gg, gj /= gg;
}
mod[i] *= gi;
mod[j] *= gj;
b[i] = modulo(b[i], mod[i]);
b[j] = modulo(b[j], mod[j]);
}
}
}
// x ≡ b(mod m)を満たすx(mod M (= lcm m))
T get(vector<T> &b, vector<T> &mod) {
// x ≡ 0(mod 1)は全ての整数
T x = 0, MOD = 1;
for(int i = 0; i < (int)b.size(); ++i) {
T p, _q;
T d = exGCD(MOD, mod[i], p, _q);
// 必要十分性の確認
if((x - b[i]) % d != 0) throw "NOT FOUND";
// nextMOD = MOD * (mod[i] / d)なので部分的にmodが取れてオーバーフロー回避
x = x - modulo((x - b[i]) / d * p, (mod[i] / d)) * MOD;
// lcm(M, m) = M * m / gcd(M, m)
MOD = MOD * (mod[i] / d);
x = modulo(x, MOD);
}
return modulo(x, MOD);
}
T Garner(vector<T> &b, vector<T> &mod, T MOD = numeric_limits<T>::max()) {
try {
normalisation(b, mod);
}
catch(...) {
throw "NOT FOUND";
}
vector<T> p(b.size());
for(int i = 0; i < (int)b.size(); ++i) {
p[i] = b[i] % mod[i];
for(int j = 0; j < i; ++j) {
T inv, _tmp;
exGCD(mod[j], mod[i], inv, _tmp);
inv = modulo(inv, mod[i]);
p[i] = (p[i] - p[j]) * inv;
p[i] = modulo(p[i], mod[i]);
}
}
// 復元
T ret = 0;
for(int i = 0; i < (int)b.size(); ++i) {
T tmp = modulo(p[i], MOD);
for(int j = 0; j < i; ++j) {
tmp *= mod[j];
tmp = modulo(tmp, MOD);
}
ret += tmp;
ret = modulo(ret, MOD);
}
return ret;
}
};
int main() {
const int MOD = 1e9 + 7;
int n; cin >> n;
vector<int64_t> x(n), y(n);
for(int i = 0; i < n; ++i) {
cin >> x[i] >> y[i];
}
ChineseRemainderTheorem<int64_t> crt;
try {
int64_t ans = crt.Garner(x, y, MOD);
cout << ans << '\n';
}
catch(...) {
cout << -1 << '\n';
}
return 0;
}
// int main() {
// const int n = 3;
// vector<int64_t> x(n), y(n);
// for(int i = 0; i < n; ++i) {
// cin >> x[i] >> y[i];
// }
// ChineseRemainderTheorem<int64_t> crt;
// try {
// int64_t ans = crt.get(x, y);
// if(ans == 0) {
// ans = 1;
// for(int i = 0; i < n; ++i) {
// ans = ans * y[i] / crt.exGCD(ans, y[i]);
// }
// }
// cout << ans << '\n';
// }
// catch(...) {
// cout << -1 << '\n';
// }
// return 0;
// }
東前頭十一枚目