結果
| 問題 |
No.187 中華風 (Hard)
|
| コンテスト | |
| ユーザー |
ate
|
| 提出日時 | 2020-09-11 06:46:56 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 171 ms / 3,000 ms |
| コード長 | 3,681 bytes |
| コンパイル時間 | 3,205 ms |
| コンパイル使用メモリ | 205,300 KB |
| 最終ジャッジ日時 | 2025-01-14 09:29:52 |
|
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 25 |
ソースコード
#include<tuple>
#include<cstdint>
template<class T = int64_t>
constexpr inline T mod(T a,T m){
a %= m;
return (a<0?a+m:a);
}
template<class T = int64_t>
std::tuple<T,T,T> ext_gcd(T a,T b){
if(b==0){
return {a,1,0};
}
auto [d,y,x] = ext_gcd(b,a%b);
y -= a/b * x;
return {d,x,y};
}
template<class T = int64_t>
T mod_inv(T a,T m){
auto[d,x,y] = ext_gcd(a,m);
return (d!=1?-1:mod(x,m));
}
#include<vector>
#include<cassert>
template<class T = int64_t>
T gerner(std::vector<T> const& b,std::vector<T> const& m){
assert(0<std::size(b));
assert(std::size(b)==std::size(m));
T prod_m = 1;
T x = b[0]%m[0];
for(int i=1;i<std::size(b);++i){
prod_m *= m[i-1];
T mij = mod_inv(prod_m,m[i]);
T t = mod((b[i]-x)*mij,m[i]);
x += t*prod_m;
}
return x;
}
int64_t gerner (std::vector<int64_t> b,std::vector<int64_t> m,int64_t const MOD){
using i64 = int64_t;
assert(0<std::size(b));
assert(std::size(b)==std::size(m));
m.emplace_back(MOD);
std::vector<i64> coeffs(std::size(m),1);
std::vector<i64> constants(std::size(m),0);
for(int k=0;k<std::size(b);++k){
i64 m_inv = mod_inv(coeffs[k],m[k]);
i64 t = mod((b[k]-constants[k])*m_inv,m[k]);
for(int i=k+1;i<std::size(m);++i){
(constants[i] += t*coeffs[i]) %= m[i];
(coeffs[i] *= m[k]) %= m[i];
}
}
return constants.back();
}
#include<bits/stdc++.h>
int64_t operator"" _i64(unsigned long long x){
return (int64_t)x;
}
void solve_yuki_187(){
using namespace std;
using i64 = int64_t;
constexpr i64 MOD = 1e9+7;
int n;
cin>>n;
vector<i64> x(n),y(n);
for(int i=0;i<n;++i)cin>>x[i]>>y[i];
i64 sum = accumulate(begin(x),end(x),0_i64,[](i64 acc,i64 xi){return acc+xi;});
// A % y[i] = x[i], A \equiv x[i] (mod. y[i])
{
// 対ごとに素にする
// m0 = 2**p0 + 3**p1 + 5**p2 + 7**p3
// m1 = 2**q0 + 3**q1 + 5**q2 + 7**q3
// のように具体的に値を割り振って計算すると指数の大きいほうが残って小さいほうが0になるのがわかる
for(int i=0;i+1<n;++i){
for(int j=i+1;j<n;++j){
i64 m0 = y[i];
i64 m1 = y[j];
i64 d = gcd(m0,m1);
if(sum and (x[i]-x[j])%d!=0){
// 構築不可能
cout<< -1 <<endl;
exit(0);
}
i64 u0 = m0/d;
i64 u1 = m1/d;
i64 d0 = gcd(u0,d);
i64 d1 = d/d0;
do{
d = gcd(d0,d1);
d0 *= d;
d1 /= d;
}while(d!=1);
y[i] = u0*d0;
y[j] = u1*d1;
x[i] %= y[i];
x[j] %= y[j];
}
}
}
{
if(sum==0){
// x がすべて 0 のとき lcm(y) が答え, y は互いに素なので掛けるだけでいい
i64 lcm_y = 1;
for(i64 const& yi:y)(lcm_y*=yi)%=MOD;
cout<< lcm_y <<endl;
exit(0);
}
}
i64 ans = gerner(x,y,MOD);
cout<< ans <<endl;
}
int main(){
solve_yuki_187();
}
void solve1(){
using namespace std;
using i64 = int64_t;
vector<i64> pairwise_coprime = {7,11,13,16,17,19,23,25,27,29};
auto contain = [&pairwise_coprime](int b_1){return binary_search(begin(pairwise_coprime),end(pairwise_coprime),b_1);};
vector<i64> a(31),r,m=pairwise_coprime;
for(int b=2;b<=30;++b){
cin>>a[b];
if(contain(b-1))
r.emplace_back(a[b]%(b-1));
}
i64 ans = gerner(r,m);
if(ans==25)exit(1);
auto invalid = [](){
cout<<"invalid"<<endl;
exit(0);
};
auto digit_sum = [](i64 x,i64 b){
i64 sum = 0;
while(x){
sum += x%b;
x /= b;
}
return sum;
};
if(ans>1e12)invalid();
for(int b=2;b<=30;++b)
if(a[b] != digit_sum(ans,b))
invalid();
cout<<ans<<endl;
}
ate