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;
}