結果
問題 | No.261 ぐるぐるぐるぐる!あみだくじ! |
ユーザー | t98slider |
提出日時 | 2023-02-19 18:41:59 |
言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 3 ms / 5,000 ms |
コード長 | 5,768 bytes |
コンパイル時間 | 2,469 ms |
コンパイル使用メモリ | 193,336 KB |
実行使用メモリ | 5,376 KB |
最終ジャッジ日時 | 2024-07-20 17:35:21 |
合計ジャッジ時間 | 3,853 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge5 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 37 |
ソースコード
#include <bits/stdc++.h> using namespace std; using ll = long long; template<class T> ostream& operator<<(ostream& os, const vector<T>& vec) {if(vec.empty())return os;os << vec[0];for(auto it = vec.begin(); ++it!= vec.end();)os << ' ' << *it;return os;} struct dsu { public: int csz; dsu() : _n(0) {} dsu(int n) : _n(n), csz(n), parent_or_size(n, -1) {} int merge(int a, int b) { assert(0 <= a && a < _n); assert(0 <= b && b < _n); int x = leader(a), y = leader(b); if (x == y) return x; if (-parent_or_size[x] < -parent_or_size[y]) std::swap(x, y); csz--; parent_or_size[x] += parent_or_size[y]; parent_or_size[y] = x; return x; } bool same(int a, int b) { assert(0 <= a && a < _n); assert(0 <= b && b < _n); return leader(a) == leader(b); } int leader(int a) { assert(0 <= a && a < _n); if (parent_or_size[a] < 0) return a; return parent_or_size[a] = leader(parent_or_size[a]); } int size(int a) { assert(0 <= a && a < _n); return -parent_or_size[leader(a)]; } std::vector<std::vector<int>> groups() { std::vector<int> leader_buf(_n), group_size(_n); for (int i = 0; i < _n; i++) { leader_buf[i] = leader(i); group_size[leader_buf[i]]++; } std::vector<std::vector<int>> result(_n); for (int i = 0; i < _n; i++) { result[i].reserve(group_size[i]); } for (int i = 0; i < _n; i++) { result[leader_buf[i]].push_back(i); } result.erase( std::remove_if(result.begin(), result.end(), [&](const std::vector<int>& v) { return v.empty(); }), result.end()); return result; } private: int _n; // root node: -1 * component size // otherwise: parent std::vector<int> parent_or_size; }; constexpr long long safe_mod(long long x, long long m) { x %= m; if (x < 0) x += m; return x; } 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}; } 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; } std::pair<long long, long long> crt(const std::vector<long long>& r, const std::vector<long long>& m) { assert(r.size() == m.size()); int n = int(r.size()); long long r0 = 0, m0 = 1; for (int i = 0; i < n; i++) { assert(1 <= m[i]); long long r1 = safe_mod(r[i], m[i]), m1 = m[i]; if (m0 < m1) { std::swap(r0, r1); std::swap(m0, m1); } if (m0 % m1 == 0) { if (r0 % m1 != r1) return {0, 0}; continue; } long long g, im; std::tie(g, im) = inv_gcd(m0, m1); long long u1 = (m1 / g); if ((r1 - r0) % g) return {0, 0}; long long x = (r1 - r0) / g % u1 * im % u1; r0 += x * m0; m0 *= u1; if (r0 < 0) r0 += m0; } return {r0, m0}; } int main(){ ios::sync_with_stdio(false); cin.tie(0); int n, k; cin >> n >> k; vector<int> a(n), pos(n); dsu uf(n); iota(a.begin(), a.end(), 0); for(int i = 0; i < k; i++){ int u, v; cin >> u >> v; swap(a[--u], a[--v]); } for(int i = 0; i < n; i++)uf.merge(i, a[i]); auto G = uf.groups(); vector<vector<vector<int>>> tb; auto cov = [&](vector<int> &a, vector<int> &b){ vector<int> res(a.size()); for(int i = 0; i < a.size(); i++) res[i] = b[a[i]]; return res; }; for(auto &&vec:G){ int m = vec.size(); vector<int> c, pos(m); vector<vector<int>> temp; sort(vec.begin(), vec.end()); for(auto &v:vec) c.push_back(a[v]); for(int i = 0; i < m; i++){ int j = lower_bound(vec.begin(), vec.end(), c[i]) - vec.begin(); pos[j] = i; } //cerr << pos << '\n'; vector<int> d(m), nxt(m); iota(d.begin(), d.end(), 0); for(int i = 0; i < m; i++){ //cerr << d << '\n'; temp.push_back(cov(d, vec)); for(int j = 0; j < m; j++){ nxt[pos[j]] = d[j]; } swap(d, nxt); } tb.push_back(temp); } auto comp = [&](int i, vector<int> &temp){ for(int j = 0; j < G[i].size(); j++){ //cerr << tb[i][j] << " " << temp << '\n'; if(tb[i][j] == temp) return j; } return -1; }; int Q; cin >> Q; while(Q--){ vector<int> c(n); vector<ll> r(G.size()), mo(G.size()); for(auto &v:c)cin >> v, v--; bool is_zero = false; for(int i = 0; i < G.size(); i++){ int m = G[i].size(); vector<int> temp; for(auto &v:G[i])temp.push_back(c[v]); //cerr << temp << '\n'; r[i] = comp(i, temp); mo[i] = m; if(r[i] == -1){ is_zero = true; break; } } if(is_zero){ cout << -1 << '\n'; continue; } auto p = crt(r, mo); if(p.first == 0)p.first += p.second; cout << p.first << '\n'; } }