UVA 557 Burger

UVA_557

    这个题目再一次让我体会了一下数学的简洁美……

    首先来说,我们直接计算所求概率是比较困难的,因为我们要考虑硬币抛到谁那之后就不再抛了,但是如果我们反过来去求不符合要求的概率是比较简便的,因为必然硬币直到最后时刻都会一直在抛,那么对于任意一种最终的不符合要求的情况,都是等可能事件。

    那么我们只要把所有不符合要求的情况种数找到,再乘以每种情况的概率2^(2-n)即可。不符合要求的情况的种数用组合数也比较容易算出来,是C((n-2)/2,n-2),即在前n-2个位置随意取(n-2)/2个位置放上汉堡。

    根据上面的分析我们会发现f(n)=2^(2-n)*C((n-2)/2,n-2),但如果直接计算的话,即便边乘边除对于大数据也会超出表示范围,倒不是因为最终结果的问题,因为p总是小于1的,而是中间的计算结果会超出表示范围。

    再者,即便设计得十分合理,没有超范围,最后也会超时的,那么我们必然要保留中间结果并加以利用才可以。受组合数的递推计算式的启发,对于f(n)的计算我们是否也可以用递推的方式计算呢?显然可以,因为我们有了f(n)的通项公式嘛,而且化成递推式后,我们会发现它出乎意料得简练f(n)=(n-3)/(n-2)*f(n-2)。

#include<stdio.h>
#include<string.h>
#include<math.h>
#define MAXD 100010
double f[MAXD];
void prepare()
{
int i, n;
f[2] = 1;
for(i = 4; i <= 100000; i ++)
f[i] = f[i - 2] * (i - 3) / (i - 2);
}
int main()
{
int t, n;
prepare();
scanf("%d", &t);
while(t --)
{
scanf("%d", &n);
printf("%.4lf\n", 1 - f[n]);
}
return 0;
}



原文地址:https://www.cnblogs.com/staginner/p/2286151.html