結果
問題 | No.187 中華風 (Hard) |
ユーザー | tonegawa |
提出日時 | 2021-02-07 20:07:10 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 29 ms / 3,000 ms |
コード長 | 7,274 bytes |
コンパイル時間 | 1,959 ms |
コンパイル使用メモリ | 155,760 KB |
実行使用メモリ | 6,944 KB |
最終ジャッジ日時 | 2024-07-04 13:16:54 |
合計ジャッジ時間 | 3,285 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 7 ms
6,812 KB |
testcase_01 | AC | 6 ms
6,940 KB |
testcase_02 | AC | 21 ms
6,940 KB |
testcase_03 | AC | 21 ms
6,944 KB |
testcase_04 | AC | 28 ms
6,940 KB |
testcase_05 | AC | 29 ms
6,944 KB |
testcase_06 | AC | 29 ms
6,940 KB |
testcase_07 | AC | 28 ms
6,940 KB |
testcase_08 | AC | 15 ms
6,944 KB |
testcase_09 | AC | 15 ms
6,944 KB |
testcase_10 | AC | 15 ms
6,944 KB |
testcase_11 | AC | 28 ms
6,940 KB |
testcase_12 | AC | 28 ms
6,940 KB |
testcase_13 | AC | 4 ms
6,940 KB |
testcase_14 | AC | 4 ms
6,944 KB |
testcase_15 | AC | 7 ms
6,944 KB |
testcase_16 | AC | 7 ms
6,940 KB |
testcase_17 | AC | 2 ms
6,944 KB |
testcase_18 | AC | 5 ms
6,940 KB |
testcase_19 | AC | 2 ms
6,944 KB |
testcase_20 | AC | 23 ms
6,944 KB |
testcase_21 | AC | 2 ms
6,940 KB |
testcase_22 | AC | 29 ms
6,940 KB |
testcase_23 | AC | 2 ms
6,940 KB |
testcase_24 | AC | 2 ms
6,944 KB |
ソースコード
#include <iostream> #include <string> #include <vector> #include <array> #include <stack> #include <queue> #include <deque> #include <algorithm> #include <set> #include <map> #include <unordered_map> #include <bitset> #include <cmath> #include <functional> #include <cassert> #include <iomanip> #include <numeric> #include <memory> #include <random> #define VV(a, b, c, d) vector<vector<d>>(a, vector<d>(b, c)) #define VVV(a, b, c, d, e) vector<vector<vector<e>>>(a, VV(b, c, d, e)); #define all(obj) (obj).begin(), (obj).end() typedef long long int ll; typedef long double ld; typedef std::vector<ll> v1; typedef std::vector<v1> v2; typedef std::vector<v2> v3; using namespace std; namespace fact{ struct MontgomeryReduction{ __uint128_t MOD, NEG_INV, R2; MontgomeryReduction(uint64_t MOD_): MOD(MOD_){ NEG_INV = 0; __uint128_t s = 1, t = 0; for(int i=0;i<64;i++){ if (~t & 1) { t += MOD; NEG_INV += s; } t >>= 1; s <<= 1; } R2 = ((__uint128_t)1<<64) % MOD; R2 = R2 * R2 % MOD; } // return x * R % MOD; inline uint64_t generate(uint64_t x) const{ return reduce((__uint128_t)x * R2); } // return x / R % MOD; inline uint64_t reduce(__uint128_t x) const{ x = (x + ((uint64_t)x * (uint64_t)NEG_INV) * MOD) >> 64; return x < MOD? x: x-MOD; } }; uint64_t gcd(uint64_t a, uint64_t b){ if(a == 0) return b; if(b == 0) return a; int shift = __builtin_ctzll(a | b); a >>= __builtin_ctzll(a); do { b >>= __builtin_ctzll(b); if(a > b) std::swap(a, b); b -= a; }while(b); return (a << shift); } bool is_prime(uint64_t n, const MontgomeryReduction &mr){ if(n<=1) return false; if(n==2) return true; if(!(n&1)) return false; uint64_t d = n - 1, one = mr.generate(1); while(!(d&1)) d >>= 1; for(uint64_t a : {2, 325, 9375, 28178, 450775, 9780504, 1795265022}){ if(n <= a) break; uint64_t t = d; auto modpow = [&](uint64_t x, uint64_t k){ uint64_t r = one; while(k){ if(k&1) r = mr.reduce((__uint128_t)r * x); x = mr.reduce((__uint128_t)x * x); k >>= 1; } return r; }; uint64_t y = modpow(mr.generate(a), t), n_minus_one = mr.generate(n-1); while(t != n-1 && y != one && y != n_minus_one){ y = mr.reduce((__uint128_t)y * y); t <<= 1; } if(y != n_minus_one && t % 2 == 0) return false; } return true; } uint64_t rho(uint64_t n){ if((n&1)==0) return 2; for(auto p:{3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41}){ if(n%p==0) return p; if(n<p) break; } MontgomeryReduction mr(n); if(is_prime(n, mr)) return n; uint64_t m = 1LL << ((64 - __builtin_clzll(n)) / 8); uint32_t c = 0; auto f = [&](uint64_t num){ uint64_t tmp = mr.generate(num); tmp = mr.reduce(mr.reduce((__uint128_t)tmp * tmp)) + c; return tmp >= n ? tmp - n : tmp;}; while(true){ c = (3 * c + 1)%99; uint64_t y = 2, r = 1, q = 1, g = 1, ys, x; while(g==1){ x = y; for(int i=0;i<r;i++) y = f(y); uint64_t k = 0; while(k < r && g == 1){ q = mr.generate(q); ys = y; for(int j=0;j<min(m, r-k);j++){ y = f(y); q = mr.reduce((__uint128_t)q * mr.generate(x>y?x-y:y-x)); } g = gcd(mr.reduce(q), n); k += m; } r <<= 1; } if(g==n){ while(g==1){ ys = f(ys); g = gcd(n, (x>y?x-y:y-x)); } } if(g<n) return g; } } vector<ll> factorize(ll n) { if(n == 1) return {}; ll x = rho(n); if(x == n) return {x}; vector<ll> le = factorize(x); vector<ll> ri = factorize(n / x); le.insert(le.end(), ri.begin(), ri.end()); return le; } vector<ll> PrimeFactor(ll N){ vector<ll> p = factorize(N); sort(all(p)); decltype(p)::iterator result = std::unique(p.begin(), p.end()); p.erase(result, p.end()); return p; } vector<ll> DivisorRestore(ll N){ vector<ll> p = factorize(N); sort(all(p)); vector<vector<ll>> x(1, {1}); ll num = 1, idx = 0; for(int i=0;i<p.size();i++){ num *= p[i]; x[idx].push_back(num); if(i!=p.size()-1&&p[i+1]!=p[i]){ x.push_back(vector<ll>{1}); num = 1; idx++; } } ll l = 0, r = 1; vector<ll> ret{1}; for(int i=0;i<x.size();i++){ for(auto e:x[i]){ for(int j=l;j<r;j++){ ret.push_back(ret[j] * e); } } l = r; r = ret.size(); } return vector<ll>(ret.begin()+l, ret.end()); } } template<typename T> T mod_inv(T a, T MOD){ T u[] = {a, 1, 0}, v[] = {MOD, 0, 1}, t; while(*v){ t = *u / *v; swap(u[0] -= t * v[0], v[0]); swap(u[1] -= t * v[1], v[1]); swap(u[2] -= t * v[2], v[2]); } u[1] %= MOD; return (u[1] < 0) ? (u[1] + MOD) : u[1]; } template<int MOD> int mod_inv(int a){ int u[] = {a, 1, 0}, v[] = {MOD, 0, 1}, t; while(*v){ t = *u / *v; swap(u[0] -= t * v[0], v[0]); swap(u[1] -= t * v[1], v[1]); swap(u[2] -= t * v[2], v[2]); } u[1] %= MOD; return (u[1] < 0) ? (u[1] + MOD) : u[1]; } //A_i = x_i mod m_i //-> lcm(m)以下のmodで全ての条件を満たす数を返す //xが全て0の場合は0 //unsafe: 互いに素かつ解が必ず存在する O(N^2) ll garner_unsafe(const vector<ll>&x, vector<ll> m, ll MOD){ int n = x.size(); assert(n == m.size()); vector<ll> kp(n+1, 0), rmult(n+1, 1); m.push_back(MOD); for(int i=0;i<n;i++){ ll y = ((x[i] - kp[i]) * mod_inv<ll>(rmult[i], m[i])) % m[i]; if(y < 0) y += m[i]; for(int j=i+1;j<=n;j++){ kp[j] = (kp[j] + rmult[j] * y) % m[j]; rmult[j] = (rmult[j] * m[i]) % m[j]; } } return kp[n]; } //A_i = x_i mod m_i //-> lcm(m)以下のmodで全ての条件を満たす数を返す //xが全て0の場合は0 //互いに素でない場合、 解が存在しない場合も使える O((Nlog(M_MAX))^2 + N * M_MAX^(1/4)) ll garner(const vector<ll> x, vector<ll> m, ll MOD){ int n = x.size(); assert(n == m.size()); unordered_map<ll, vector<pair<ll, ll>>> mp; bool f = false; for(int i=0;i<n;i++){ if(x[i]) f = true; auto prime = fact::PrimeFactor(m[i]); for(auto p:prime){ ll num = 1, mi = m[i]; while(mi % p == 0){ mi /= p; num *= p; } mp[p].emplace_back(x[i] % num, num); } } if(!f){ ll ans = 1; for(auto &k:mp){ ll max_p = -1, mo = -1; for(auto pa:k.second) if(pa.second > max_p) max_p = pa.second, mo = pa.first; ans = (ans * max_p) % MOD; } return ans; } vector<ll> x2, m2; for(auto &k:mp){ ll max_p = -1, mo = -1; for(auto pa:k.second) if(pa.second > max_p) max_p = pa.second, mo = pa.first; for(auto pa:k.second) if(mo % pa.second != pa.first) return -1; x2.push_back(mo); m2.push_back(max_p); } return garner_unsafe(x2, m2, MOD); } int main(){ int n;std::cin >> n; vector<ll> x(n), m(n); for(int i=0;i<n;i++) std::cin >> x[i] >> m[i]; std::cout << garner(x, m, 1000000007) << '\n'; }