hdu 3625 Examining the Rooms(第一类斯特林数)

传送门

解题思路

  首先门其实形成了若干个环,每次可以将这个环内的所有门都打开。这样就可以想到第一类斯特林数,设\(f[i][j]\)表示把前\(i\)个数字划分成\(j\)个环的方案,\(f[i][j]=(i-1)f[i-1][j]+f[i-1][j-1]\)。然后注意还要把不能炸第一个这个条件考虑到。最后的答案为\(\dfrac{\sum\limits_{i=1}^k f[n][i]-f[n-1][i-1]}{n!}\)

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
const int MAXN = 22;
typedef long long LL;

inline int rd(){
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
	while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
	return f?x:-x;	
}

int T,n,k;
LL ans,fac[MAXN],f[MAXN][MAXN];

int main(){
	fac[1]=1;f[0][0]=1;
	for(int i=2;i<=20;i++) fac[i]=fac[i-1]*i;
	for(int i=1;i<=20;i++)
		for(int j=1;j<=i;j++)
			f[i][j]=(i-1)*f[i-1][j]+f[i-1][j-1];
	T=rd();
	while(T--){
		n=rd(),k=rd();ans=0;
		for(int i=1;i<=k;i++) ans+=f[n][i]-f[n-1][i-1];
		printf("%.4lf\n",(double)ans/fac[n]);
	}
	return 0;	
}
posted @ 2018-12-05 14:58  Monster_Qi  阅读(96)  评论(0编辑  收藏  举报