UVa 557 - Burger

这个题向我充分展示了数学的简洁之美。 


自己做的时候是从正面做的, 推出了个公式 ∑ (1/2)^(2n-k)*C(2n-k-1, n-k) (2<=k<=n,  n是总人数的一半)。 结果这个公式超时不说, 可以打表, 但精度不够, 大概2000+就不行了。 又发现一个规律可以把时间降到o(n), 但是精度损失更大。


还是得看题解, 都是反着求得:已确定最后俩个人的汉堡是不一样的, 那么前面每次都会抛硬币, 概率为(1/2)^(n-2), (n是总人数, 下同), 选(n-2)/2个人拿同一种汉堡, 则剩下的人拿另一种, 组合数为C(n-2, (n-2)/2), 答案就是(1/2)^(n-2)*C(n-2, (n-2)/2)。 

这样做估计还是超时, 不过可以打表了。


还可以继续优化, 找出递推公式, 边界f(2)=1, f(n)=f(n-2)*(n-3)/(n-2)。 竟然可以这么简单。



#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <string>
#include <set>
#include <map>
#include <list>
#include <vector>
#include <queue>
#include <stack>
#include <sstream>
#include <iomanip>
typedef long long ll;
typedef unsigned long long llu;
using namespace std;

int main()
{
    double f[100000+10];
    f[2]=1.0;
    for(int i=4; i<=100000+5; i+=2)
        f[i]=f[i-2]*(i-3)/(i-2);
    int n, t;
    cin>>t;
    while(t-- && scanf("%d", &n))
        printf("%.4lf\n", 1-f[n]);
    return 0;
}



以下是自己写的超时又精度不够的程序。 水平还是太菜。 



#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <string>
#include <set>
#include <map>
#include <list>
#include <vector>
#include <queue>
#include <stack>
#include <sstream>
#include <iomanip>
typedef long long ll;
typedef unsigned long long llu;
using namespace std;

double fun(int n, int m)
{
    double ans=0.5;
    double i=1.0;
    for(int j=1.0; j<=m; j++, i++)
        ans*=0.5;
    for(int j=1.0; j<=n-m; j++, i++)
        ans*=i/j*0.5;
    return ans;
}

//double fun(int n, int m)
//{
//    double ans=0.5;
//    for(double i=1.0; i<=m; i++)
//        ans=ans*(n-i+1.0)/i*0.5;
//    for(int i=0; i<n-m; i++)
//        ans*=0.5;
//    return ans;
//}

double solve(int n)
{
    double ans=0;
    for(int k=2; k<=n; k++)
        ans+=fun(2*n-k-1, n-k);
    return ans;
}

int main()
{
    int n, t;
    cin>>t;
    while(t-- && scanf("%d", &n))
        printf("%.4lf\n", 2*solve(n/2));
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值