您的位置:首页 > 其它

Uva 11077 Find the Permutations [置换群 DP]

2017-02-28 18:44 447 查看
题意:

给定$n$和$k$,问有多少排列交换$k$次能变成升序

$n \le 21$

$uva$貌似挂掉了$vjudge$上一直排队

从某个排列到$1,2,...,n$和从$1,2,...,n$到某个排列是一样的

排列就是置换,分解循环,然后显然每个循环变成升序需要$len-1$次交换

然后有$t$个循环的置换需要$n-t$次交换

$DP$就行了$f[i][j]$表示前$i$个数有$j$个循环

其实可以发现就是第一类$stirling$数

注意:以后一定要测一遍极限会爆$long\ long$

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=30;
typedef unsigned long long ll;
inline int read(){
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
return x*f;
}
int n,k;
ll f

;
void dp(){
f[0][0]=1;
for(int i=1;i<=21;i++)
for(int j=1;j<=21;j++)
f[i][j]=f[i-1][j-1]+f[i-1][j]*(i-1);
}
int main(){
//freopen("in","r",stdin);
dp();
while(true){
n=read();k=read();
if(n==0&&k==0) break;
printf("%llu\n",f
[n-k]);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: