Initially, we have the array \{1, 2, ..., n\}. Then a shuffling procedure is performed. We are given the final permutation . We need to find the probability that this exact permutation is obtained after the procedure.
The required probability is equal to:
At each step of the shuffle, a number is chosen. There are possible choices for . The number of shuffling steps is also . Therefore, there are n^n possible sequences of choices. Note that different sequences of choices may lead to the same final permutation, because n^n is much larger than .
Let us store the sequence \{1, 2, ..., n\} in the array . We'll iterate over all possible choices (r_1, r_2, ..., r_n), simulating in every possible shuffling process (1 \le r_i \le n). Note that a fixed sequence of numbers r_1, r_2, ..., r_n uniquely determines which swaps are performed at each step, and therefore also determines the final array after the procedure is completed. If, after applying all swaps, we obtain the array , we count the attempt as successful. Let the number of such successful attempts be . Then the required probability is equal to
Let's implement the shuffle function, which recursively enumerates all possible continuations of the shuffling process and counts how many of them lead to the target permutation .
The function has one parameter , the index of the current iteration (starting from ). This means that the first swaps have already been performed, and the array stores the state obtained after these operations.
To fit within the time limit, apply the following pruning. Suppose we are at iteration , and the current array differs from the target array in positions. There are n - pos swaps left to perform. Note that a single swap can place at most two elements into their correct positions. Therefore, over the remaining steps we can fix no more than 2 \cdot (n - pos) positions in total.
If diff > 2 \cdot (n - pos), then it is already impossible to transform into . In this case, continuing the search makes no sense, and the current branch of the recursion can be terminated immediately.
Algorithm implementation
Let us declare the following arrays:
— the given permutation ;
— the current permutation during the enumeration;
int a[10], cur[10];The shuffle function recursively enumerates all possible continuations of the shuffling process, counting how many of them lead to the target permutation .
void shuffle(int pos)
{After all operations have been performed, it remains to check whether the obtained array matches the required permutation . If it does, then we have found another successful scenario. In this case, increment .
if (pos == n)
{
for (int i = 0; i < n; i++)
if (cur[i] != a[i]) return;
countGood++;
return;
}In the variable , count the number of positions where the current array differs from the required permutation .
int diff = 0;
for (int i = 0; i < n; i++)
if (cur[i] != a[i]) diff++;At this point, we still have n - pos steps left to perform. A single swap can fix at most two incorrect positions. If the number of differences already exceeds what can possibly be fixed, then continuing the recursion is pointless.
So we simply stop exploring this branch of the search.
if (diff > 2 * (n - pos)) return;Iterate over all possible values of .
for (int r = 0; r < n; r++)
{
swap(cur[pos], cur[r]);
shuffle(pos + 1);
swap(cur[pos], cur[r]);
}
}The main part of the program. Read the number — the size of array .
while (scanf("%d", &n) == 1)
{Read the input array . The simulation always starts with the array \{1, 2, ..., n\}, which we store in .
for (int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
cur[i] = i + 1;
}Start the enumeration. The variable counts how many sequences of random choices lead to the array .
countGood = 0;
shuffle(0);Compute and print the result.
res = countGood / pow(n, n);
printf("%.6lf\n", res);
}