HDU3265 Examining the Rooms【stirling数】

题目链接:

?pid=3625

题目大意:

有N个房间,每个房间的要是随机放在某个房间内,概率相同。有K次炸门的机会。

求能打开所有房间门,进入所有房间的概率有多大。

解题思路:

门和钥匙的对应关系出现环。打开一个门后,环内的门都可以打开。也就意味着:

N个房间的钥匙与门形成1~K个环的概率有多大。

也就是求N个元素,构成K个以内的环,且1不成自环的概率。

N个元素形成K个环的方法数是第一类stirling数 S(N,K)。

N个元素形成K个环,且1成自环的方法数是S(N-1,K-1)。

则N个元素形成K个环,且1不成自环的方法数是S(N,K) – S(N-1,,K-1)。

要是随机放的总的方法数为N!。

则概率P(N,K)为( S(N,K) – S(N-1,K-1) + S(N,K-1) – S(N-1,K-2) + … +

S(N,1) – S(N,0) ) / N!

AC代码:

#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#define LL long longusing namespace std;LL F[25],Stirling[25][25];void Solve(){F[0] = 1;for(int i = 1; i <= 20; ++i) //阶乘数组F[i] = i*F[i-1];for(int i = 1; i <= 20; ++i) //算出第一类stirling数Stirling[i][0] = 0;Stirling[1][1] = 1;for(int i = 1; i <= 20; ++i){for(int j = 1; j <= i; ++j){if(i == j)Stirling[i][j] = 1;elseStirling[i][j] = Stirling[i-1][j-1] + (i-1)*Stirling[i-1][j];}}for(int i = 1; i <= 20; ++i) //取绝对值{for(int j = 1; j <= 20; ++j){Stirling[i][j] = abs(Stirling[i][j]);}}}int main(){Solve();int T,N,K;scanf("%d",&T);while(T–){scanf("%d %d",&N,&K);LL sum = 0;for(int i = 1; i <= K; ++i)sum += Stirling[N][i] – Stirling[N-1][i-1];printf("%.4f\n",(double)sum / (double)F[N]); //.4lf输出不了正确结果}return 0;}

版权声明:本文为博主原创文章,未经博主允许不得转载。

要铭记在心;每天都是一年中最美好的日子

HDU3265 Examining the Rooms【stirling数】

相关文章:

你感兴趣的文章:

标签云: