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

猜你喜欢

转载自www.cnblogs.com/sdfzsyq/p/10070952.html