链接
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2018
题解
这题主要难在它的数学建模
这题可以看成图论
对于一个置换,我可以把它看作一张有向图,每个节点的出度和入读都为
1
1
1,这样的图只能是若干个环,而且每种不同形态的图都和一个置换一一对应
假设一共有
x
x
x个环,那么这张图对应的排列的交换次数就是
N
−
x
N-x
N−x
所以最终就是问你有多少种不同的图,使得环数等于
N
−
k
N-k
N−k
考虑每次加入第
i
i
i个节点,
f
(
i
,
j
)
f(i,j)
f(i,j)表示
i
i
i个结点且有
j
j
j个环的图有多少种
加入一个结点时,这个点要么自己成一个环,要么丢到别的环里去(可以接到任何一个点的后面)
f
(
i
,
j
)
=
f
(
i
−
1
,
j
−
1
)
+
f
(
i
−
1
,
j
)
∗
(
i
−
1
)
f(i,j)=f(i-1,j-1)+f(i-1,j)*(i-1)
f(i,j)=f(i−1,j−1)+f(i−1,j)∗(i−1)
代码
//图论、置换、DP
#include <bits/stdc++.h>
#define maxn 30
#define ull unsigned long long
using namespace std;
ull ans, f[maxn][maxn], N, k;
int main()
{
ull i, j;
f[0][0]=1;
for(i=1;i<maxn;i++)
{
for(j=1;j<=i;j++)f[i][j]=f[i-1][j-1]+f[i-1][j]*(i-1);
}
while(cin>>N>>k,N)
{
cout<<f[N][N-k]<<endl;
}
return 0;
}