結果
| 問題 |
No.261 ぐるぐるぐるぐる!あみだくじ!
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 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';
}
}