gym:Problem F Fleecing the Raffle(概率公式化简+递推)

				2016-2017-acmicpc-nordic-collegiate-programming-contest-ncpc-2016

F Fleecing the Raffle

题目链接 http://codeforces.com/gym/101550/attachments

题意:现在有n个人要抽奖,要抽p个人出来中奖,你可以随便放自己的名字到箱子中,数目不限,但是如果你的名字被抽到两次那抽奖作废,问你要放多少张你的名字在箱子中可以最大化你的中奖概率。

解题思路:

  • 人数最多10^6个,直接枚举就行了。但是需要考虑怎么枚举不会炸精度。
  • 假设我放x个自己的名字进去,那么中奖的概率就是C(1, x) * C(p-1, n) / C(p, n+x)。然后将公式展开,化简之后可以得到一个O(1)的递推式,递推到概率开始下降的时候停止。注意在递推的过程中要一边乘一边除,不然会炸精度。
  • 深深的愧对我的高中老师,居然把化简公式推错了,还推错了好几次。
#include <bits/stdc++.h>
using namespace std;

double n, p;

int main() {
    // freopen("1.in", "r", stdin);
    scanf("%lf%lf", &n, &p);
    double x1 = 1, x2 = p, x3 = n+1;
    double ans1 = (x1*x2)/(x3/1.0), ans2;
    for(double i=2.0;i<=n;i += 1.0) {
        x1 = i;
        x2 = p;
        x3 = x3 * (n+i)/(n-p+i);

        ans2 = (x1*x2)/x3;
        if(ans2 < ans1)
            break;
        else {
            ans1 = ans2;
        }
    }
    printf("%.10f\n", ans1);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值