3602 Counting Swaps 0x30「数学知识」例题
背景
https://ipsc.ksp.sk/2016/real/problems/c.html
Just like yesterday (in problem U of the practice session), Bob is busy, so Alice keeps on playing some single-player games and puzzles. In her newest puzzle she has a permutation of numbers from 1 to n. The goal of the puzzle is to sort the permutation using the smallest possible number of swaps.
Instead of simply solving the puzzle, Alice is wondering about the probability of winning it just by playing at random. In order to answer this question, she needs to know the number of optimal solutions to her puzzle.
描述
You are given a permutation p1, …, pn of the numbers 1 through n. In each step you can choose two numbers x < y and swap px with py.
Let m be the minimum number of such swaps needed to sort the given permutation. Compute the number of different sequences of exactly m swaps that sort the given permutation. Since this number may be large, compute it modulo 109 + 9.
输入格式
The first line of the input file contains an integer t specifying the number of test cases. Each test case is preceded by a blank line.
Each test case consists of two lines. The first line contains the integer n. The second line contains the sequence p1, …, pn: a permutation of 1, …, n.
In the easy subproblem C1, 1 ≤ n ≤ 10.
In the hard subproblem C2, 1 ≤ n ≤ 105.
输出格式
For each test case, output a single line with a single integer: x
样例输入
3
3
2 3 1
4
2 1 4 3
2
1 2
样例输出
3
2
1
样例解释
In the first test case, we can sort the permutation in two swaps. We can make the first swap arbitrarily; for each of them, there’s exactly one optimal second swap. For example, one of the three shortest solutions is “swap p1 with p2 and then swap p1 with p3”.
In the second test case, the optimal solution involves swapping p1 with p2 and swapping p3 with p4. We can do these two swaps in either order.
The third sequence is already sorted. The optimal number of swaps is 0, and thus the only optimal solution is an empty sequence of swaps.
求长度为n的环变成自环的公式
f[n]=n^(n-2)
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=100000+10; const long long mod=1000000009; long long a[maxn]; long long num[maxn]; long long l[maxn]; bool v[maxn]; long long pow(long long x,long long k){ long long ans=1%mod; for (;k;k>>=1){ if(k&1) ans=ans*x%mod; x=(long long)x*x%mod; } return ans%mod; } int main(){ //freopen("data.in","r",stdin); //freopen("data.out","w",stdout); a[0]=1; for(int i=1;i<=100000;i++) a[i]=a[i-1]*i%mod; int t; scanf("%d",&t); while(t--){ memset(v,0,sizeof(v)); int n; scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%lld",&num[i]); int top=0; for (int i=1;i<=n;i++){ if(!v[i]){ int pp=1; v[i]=true; for (int j=num[i];j!=i;j=num[j]){ ++pp; v[j]=true; } l[++top]=pp; } } long long ans=1; for (int i=1;i<=top;i++){ ans=ans*(l[i]==1 ? 1 : pow(l[i],l[i]-2))%mod; ans=ans*pow(a[l[i]-1],mod-2)%mod; } ans=ans*a[n-top]%mod; printf("%lld ",ans%mod); } return 0; }