結果
| 問題 |
No.187 中華風 (Hard)
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2023-03-23 22:34:42 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 3,021 bytes |
| コンパイル時間 | 1,822 ms |
| コンパイル使用メモリ | 176,540 KB |
| 実行使用メモリ | 6,944 KB |
| 最終ジャッジ日時 | 2024-09-18 15:40:18 |
| 合計ジャッジ時間 | 4,702 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 24 WA * 1 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
namespace crt{
long long gcd(long long p, long long q){
if(p < q)swap(p, q);
if(q == 0)return p;
return gcd(q, p%q);
}
long long extgcd(long long p,long long q,long long &s,long long &t){
if(q==0){s=1;t=0;return p;}
long long par;
par = extgcd(q,p%q,t,s);
t-=p/q*s;
return par;
}
pair<long long,long long> solve2CRT(pair<long long,long long>s,pair<long long,long long>t){long long p,q,r,x,ans;r=extgcd(s.second,t.second,p,q);if((s.first-t.first)%r!=0)return make_pair(-1,-1);x=s.second/r*t.second;ans=p*(s.first-t.first)/r;return make_pair(s.second*ans+s.first,x);}
pair<long long,long long> solveCRT(vector<pair<long long,long long>>x){auto p=make_pair(1LL,1LL);for(auto it:x){p=solve2CRT(p,it);if(p.first==-1)return p;}return p;}
//mod mにおけるaの逆元を返す。 aとmが互いに素でないときの動作はこわい。
long long inv(long long a,long long m){long long p,q;extgcd(a,m,p,q);return (p%m+m)%m;}
// (b, n)でx≡b(mod n)を表し、そのvectorを受け取ってその連立を満たす最小の組(s mod mod, t mod mod)を返す。
//要件 このアルゴリズムを使うときはすべての法が互いに素でなくてはならない
pair<long long,long long> garner(vector<pair<long long, long long>> lis, long long mod){
int n = lis.size();
lis.emplace_back(0, mod);
vector<long long> ta(n+1, 0), mooda(n+1, 1);
for(int i = 0; i < n; i++){
long long m = lis[i].second;
long long a = ((lis[i].first-ta[i])*inv(mooda[i], m)%m+m)%m;
for(int j = i+1; j < n+1; j++){
ta[j] += a*mooda[j];
ta[j] %= lis[j].second;
mooda[j] *= m;
mooda[j] %= lis[j].second;
}
}
return make_pair(ta[n], mooda[n]);
}
//互いに素でない場合でも使えてほしいgarner
pair<long long, long long> super_garner(vector<pair<long long, long long>> &v, long long mod){
int n = v.size();
for(int i = 0; i < n; i++){
for(int j = 0; j < i; j++){
long long g = gcd(v[i].second, v[j].second);
if((v[i].first-v[j].first)%g != 0) return make_pair(-1, -1);
v[i].second /= g;
v[j].second /= g;
long long gi = gcd(v[i].second, g);
long long gj = g/gi;
do{
g = gcd(gi, gj);
gi *= g;
gj /= g;
}while(g != 1);
v[i].second *= gi;
v[j].second *= gj;
v[i].first %= v[i].second;
v[j].first %= v[j].second;
}
}
long long lcm = 1;
for(int i = 0; i < n; i++){
lcm *= v[i].second;
lcm %= mod;
}
return garner(v, mod);
}
}
int main(){
int n;
cin >> n;
vector<pair<long long, long long>> v;
for(int i = 0; i < n; i++){
long long x, y;
cin >> x >> y;
v.emplace_back(x, y);
}
auto p = crt::super_garner(v, 1000000007);
if(p.first == -1) cout << -1 << endl;
else if(p.first) cout << p.first << endl;
else cout << p.second << endl;
}