Challenge: Sasha and Swaps
Subdomeniu: Combinatorics (combinatorics)
Scor cont: 100.0 / 100
Submission status: Accepted
Submission score: 1.0
Submission ID: 464735862
Limbaj: cpp14
Link challenge: https://www.hackerrank.com/challenges/sasha-and-swaps/problem
Cerinta
Little Sasha likes to swap elements in his array. Initially, he has an array of $N$ numbers $1, 2, ..., N$ in ascending order. Then, he swaps some elements in it $K$ times. He really likes this sequence of $K$ swaps and repeats it $T$ times. However, Sasha forgot his favorite swap sequence the next day.
Given the resulting permutation, find the swap sequence used by Sasha or say that there is no such sequence.
<!-- To reviewer: in Russian language Sasha is a shortened version of my name (Alexander), so he definitely considered to be a boy :) -->
Input Format
The first line of input contains three integers $N$, $K$, and $T$, respectively. <br>
The second line contains a permutation of numbers $1, 2, ..., N$.
**Constraints**
$2 \leqslant N \leqslant 10^5$
$1 \leqslant K \leqslant 10^5$
$1 \leqslant T \leqslant 2 \times 10^9$
Output Format
Print $K$ lines. The $i^{th}$ line contains two distinct integers $a_i$, $b_i$ which means that the $i^{th}$ swap will be of $a_i^{th}$ and $b_i^{th}$ numbers. If there are multiple possible answers, print any of them.<br>
Otherwise, if there is no such sequence of swaps, print "*no solution*" without quotes.
Cod sursa
#include<bits/stdc++.h>
using namespace std;
const int N = 3e5 + 9;
vector<vector<int>> decompose(vector<int> &p) {
int n = p.size();
vector<vector<int>> cycles;
vector<bool> vis(n, 0);
for (int i = 0; i < n; i++) {
if (!vis[i]) {
vector<int> v;
while (!vis[i]) {
v.push_back(i);
vis[i] = 1;
i = p[i];
}
cycles.push_back(v);
}
}
return cycles;
}
vector<int> restore(int n, vector<vector<int>> &cycles) {
vector<int> p(n);
for (auto v : cycles) {
int m = v.size();
for (int i = 0; i < m; i++) p[v[i]] = v[(i + 1) % m];
}
return p;
}
//cycle decomposition of the k-th power of p
vector<vector<int>> power(vector<int> &p, int k) {
int n = p.size();
auto cycles = decompose(p);
vector<vector<int>> ans;
for (auto v : cycles) {
int len = v.size(), g = __gcd(k, len); //g cycles of len / g length
for (int i = 0; i < g; i++) {
vector<int> w;
for (int j = i, cnt = 0; cnt < len / g; cnt++, j = (j + k) % len) {
w.push_back(v[j]);
}
ans.push_back(w);
}
}
return ans;
}
//cycle decomposition of the k-th root of p with minimum disjoint cycles
//if toggle = 1, then the parity of number of cycles will be different from the other(toggle = 0) if possible
//returns empty vector if no solution exists
vector<vector<int>> root(vector<int> &p, int k, int toggle = 0) {
int n = p.size();
vector<vector<int>> cycles[n + 1];
auto d = decompose(p);
for (auto v : d) cycles[(int)v.size()].push_back(v);
vector<vector<int>> ans;
for (int len = 1; len <= n; len++) {
if (cycles[len].empty()) continue;
int tmp = k, t = 1, x = __gcd(len, tmp);
while (x != 1) {
t *= x;
tmp /= x;
x = __gcd(len, tmp);
}
if ((int)cycles[len].size() % t != 0) {
ans.clear();
return ans; //no solution exists
}
int id = 0;
//we can merge t * z cycles iff tmp % z === 0
if (toggle && tmp % 2 == 0 && (int)cycles[len].size() >= 2 * t) {
int m = 2 * t * len;
vector<int> cycle(m);
for (int x = 0; x < 2 * t; x++) { //merging 2t cycles to perform the toggle
for (int y = 0; y < len; y++) {
cycle[(x + 1LL * y * k) % m] = cycles[len][x][y];
}
}
ans.push_back(cycle);
id = 2 * t;
toggle = 0;
}
for (int i = id; i < (int)cycles[len].size(); i += t) {
int m = t * len;
vector<int> cycle(m);
for (int x = 0; x < t; x++) { //merging t cycles
for (int y = 0; y < len; y++) {
cycle[(x + 1LL * y * k) % m] = cycles[len][i + x][y];
}
}
ans.push_back(cycle);
}
}
return ans;
}
//minimum swaps to obtain this perm from unit perm
vector<pair<int, int>> transpositions(vector<vector<int>> &cycles) {
vector<pair<int, int>> ans;
for (auto v : cycles) {
int m = v.size();
for (int i = m - 1; i > 0; i--) ans.push_back({v[0], v[i]});
}
return ans;
}
int32_t main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
int n, l, k;
cin >> n >> l >> k;
vector<int> p(n);
for (auto &x : p) cin >> x, --x;
auto a = root(p, k);
if (a.empty()) return cout << "no solution\n", 0;
auto t = transpositions(a);
if (t.size() % 2 != l % 2) {
a = root(p, k, 1);
t = transpositions(a);
}
if (t.size() % 2 != l % 2 || t.size() > l) return cout << "no solution\n", 0;
auto z = restore(n, a);
auto w = power(z, k);
auto x = restore(n, w);
assert(p == x);
for (auto x : t) cout << x.first + 1 << ' ' << x.second + 1 << '\n';
for (int i = t.size(); i < l; i++) cout << 1 << ' ' << 2 << '\n';
return 0;
}
//https://www.hackerrank.com/contests/infinitum14/challenges/sasha-and-swaps/problem
HackerRank Combinatorics – Sasha and Swaps
