1. 程式人生 > >hdu 3625 Examining the Rooms(第一類斯特林數)

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