现在的位置: 首页 > 综合 > 正文

HDU 2048 神、上帝以及老天爷

2018年04月29日 ⁄ 综合 ⁄ 共 1598字 ⁄ 字号 评论关闭
Problem Description
HDU 2006'10 ACM contest的颁奖晚会隆重开始了!
为了活跃气氛,组织者举行了一个别开生面、奖品丰厚的抽奖活动,这个活动的具体要求是这样的:

首先,所有参加晚会的人员都将一张写有自己名字的字条放入抽奖箱中;
然后,待所有字条加入完毕,每人从箱中取一个字条;
最后,如果取得的字条上写的就是自己的名字,那么“恭喜你,中奖了!”

大家可以想象一下当时的气氛之热烈,毕竟中奖者的奖品是大家梦寐以求的Twins签名照呀!不过,正如所有试图设计的喜剧往往以悲剧结尾,这次抽奖活动最后竟然没有一个人中奖!

我的神、上帝以及老天爷呀,怎么会这样呢?

不过,先不要激动,现在问题来了,你能计算一下发生这种情况的概率吗?

不会算?难道你也想以悲剧结尾?!

 

Input
输入数据的第一行是一个整数C,表示测试实例的个数,然后是C 行数据,每行包含一个整数n(1<n<=20),表示参加抽奖的人数。

 

Output
对于每个测试实例,请输出发生这种情况的百分比,每个实例的输出占一行, 结果保留两位小数(四舍五入),具体格式请参照sample output。

 

Sample Input
1 2
 

Sample Output
50.00%
 

Author
lcy
 
解题思路:
这道题,一看就是一道概率问题,计算概率的方法很多,那么最常用的是哪些方法了呢?无疑就是几何概型和古典概型这两种了,但是这两种概型下的题目,
见得不多,大都是在概率论的课本上papa就能秒出来的,QAQ。
这道题,一看就是古典概型了,计算错排个数,然后除以总的可能情况就OK了,很水的一道概率题,但是一开始自己写了两个2一维数组,感觉没有一个二
维数组来得巧,所以看了别人的代码改成了2维数组,下来来讲解下这个递推公式是怎么得到的。
假设我们有n个人,那么很容易和其他的递推题挂钩,那就是说,用自己的IQ去推理出n-1和n-2种情况,然后加法原理就能搞定n个人时候的情况。
1.  假设n-1个满足错排的话,现在又来了一个人,那么这个人手上的票当然是自己的名字了,那么这样的情况就会是这样的,让第n个人
和前n-1个人进行对换,那么就会有n-1种情况发生,依次类推,假设n-2个人满足错排,那么现在来了第n-1个人,那么让第n-1个人和前n-2
个满足错排的人进行换票,那么就有n-2种情况,,,一直递推下去,直到只有3个人的情况,因为1,2,3人的情况,凭借枚举,手算都是可以搞定
  的,QOQ!
2. 假设n-1个人不满足错排的话,也就是说,这n-1个人中有一个人手上拿的是写有自己名字的票,那么,除去这个人后,剩下的n-2个人
就会满足错排了,再来了第n个人,让这第n个人和这个不满足错排的人进行换票的话,就有n-1种情况(为什么会是n-1种情况呢?因为前n-1个人
都有拿到写有自己名字的可能),那么再依次递推下去,大家就会发现规律
最后,结合加法原理,因为这两种情况对于同一个随机事件来说是互斥的,当然就满足加法原理了,那么
f[n] = ( n - 1 )*(  f[n-1] + f[ n - 2 ] )
代码:
# include<cstdio>
# include<iostream>


using namespace std;

__int64 a[21][2] = { {0,0},{1,0},{2,1},{6,2} };

void dabiao()
{
    for ( int i = 4;i < 21;i++ )
        {
            a[i][0] = i*a[i-1][0];
            a[i][1] = (i-1)*(a[i-1][1]+a[i-2][1]);
        }
}

int main(void)
{
    dabiao();
    int t;cin>>t;
    while ( t-- )
    {
        int n;cin>>n;
        //cout<<a[n][1]<<endl;
        //cout<<a[n][0]<<endl;
        printf("%.2f%%\n",a[n][1]*100.0/a[n][0]);
    }



    return 0;
}

抱歉!评论已关闭.