HDU 3625

有点置换群的味道。

当撞开一个门后,能打开一连串的门,即是可以排成一个圈。求的是种数,于是,可以使用第一类斯特林数,求出撞了0~K次的种数。

但是,注意,当第一个门为独自一个圈时,是不可行的,因为这代表第一个门要撞开,这违犯规则。所以,把第一个门独立成圈的情况去掉。即是求出S(N-1,K-1)以前的各种情况了。减去即可。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define LL __int64

using namespace std;

LL str[21][21];
LL cn[21];
void initial(){
	cn[0]=1;
	for(LL i=1;i<=20;i++)
	cn[i]=cn[i-1]*i;
	for(LL i=0;i<=20;i++){
		for(LL j=0;j<=i;j++){
			if(i==j)
			str[i][j]=1;
			else if(j==0)
			str[i][j]=0;
			else{
				str[i][j]=(i-1)*str[i-1][j]+str[i-1][j-1];
			}
		}
	}
}

int main(){
	initial();
	int T,n,k;
	scanf("%d",&T);
	while(T--){
		scanf("%d%d",&n,&k);
		LL up=0;
		LL down=cn[n];
		for(int i=0;i<=k;i++)
		up+=str[n][i];
		for(int i=0;i<=k-1;i++)
		up-=str[n-1][i];
		double ans=(double)up/(double)down;
		printf("%0.4lf\n",ans);
	}
	return 0;
}

  

posted @ 2014-10-12 14:51  chenjunjie1994  阅读(139)  评论(0编辑  收藏  举报