Розбір
Let’s consider three permutations: , and . Let be the identity permutation. Consider the equation: . From this, we get . Using the fact that permutations are applied from right to left, this identity can be rewritten as: . Therefore, .
Generate a random permutation that has no fixed points. Then, compute the permutation and check that it has no fixed points. The found permutations and are the required ones.
Example
Consider the permutation .
Its inverse will be .
Generate a random permutation with no fixed points. For example, let . Now, let's compute its inverse: .
Next, compute . The permutation has no fixed points, so it is valid.
Algorithm realization
The print function prints the elements of the array , starting from the first one.
void print(vector<int>& a) { for (int i = 1; i < a.size(); i++) printf("%d ", a[i]); printf("\n"); }
The function is_valid checks whether the permutation contains any fixed points.
bool is_valid(vector<int>& v) { for (int i = 1; i < v.size(); i++) if (v[i] == i) return false; return true; }
Declare the arrays.
vector<int> a, p, p1, q;
The main part of the program. Read the input data.
scanf("%d", &tests); while (tests--) { scanf("%d", &n);
Initialize the arrays.
a.resize(n + 1); p1.resize(n + 1); p.resize(n + 1); q.resize(n + 1);
Read the input permutation and immediately store its inverse in the array . That is, the array contains the permutation , where is the input permutation.
for (i = 1; i <= n; i++) { scanf("%d", &x); a[x] = i; }
mt19937 is one of the standard pseudorandom number generators in C++ (Mersenne Twister with a period of 19937). It is very fast and has good statistical properties, making it an excellent choice for most tasks requiring random number generation.
mt19937 gen(random_device{}());
In the variable , we'll mark whether a solution is found for the current test.
found = false;
Perform iterations.
for (it = 0; it < 1000; it++) {
Generate a random permutation. To do this, populate the array with the numbers , and use the shuffle function to shuffle the elements, starting from the first (non-zero) element. We work with permutations from to .
iota(p.begin(), p.end(), 0); shuffle(p.begin() + 1, p.end(), gen);
Check whether the permutation is valid (i.e., it contains no fixed points).
if (!is_valid(p)) continue;
Compute the permutation .
for (i = 1; i <= n; i++) p1[p[i]] = i;
Compute the permutation .
for (i = 1; i <= n; i++) q[i] = p1[a[i]];
If the permutation is valid, print the result.
if (is_valid(q)) { puts("Possible"); print(p); print(q); found = true; break; } }
If no solution is found after iterations, then no solution exists.
if (!found) puts("Impossible"); }