题目
给定n和k(n<=21,0<k<n),求有多少长为n的排列,
至少需要交换k次,才能变成{1,...,n}
思路来源
指南P149
题解
长度为x的置换循环需要x-1交换,
类似第一类斯特林数,设f[i][j]为考虑1到i的置换时至少需要j次交换的方案数
则加入第i个数时,要么加入之前的置换循环,需要1次交换,要么新开一个,不需要交换
注意答案需要ull
代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef unsigned long long ull;
const int N=22;
int n,k;
ull f[N][N];//f[i][j]表示需要至少j次 才能交换成1到i的排列
int main(){
f[1][0]=1;//1
for(int i=2;i<=21;++i){
for(int j=0;j<i;++j){
//考虑到长为x的置换循环所需x-1次才能归位
f[i][j]=(i-1)*(j-1>=0?f[i-1][j-1]:0)+f[i-1][j];//考虑将第i个元素放入之前的置换循环 还是单开一个置换循环
}
}
while(~scanf("%d%d",&n,&k)){
if(!n && !k)break;
printf("%llu\n",f[n][k]);
}
return 0;
}