UVALive 7962|Gym 101201K|Tournament Wins|概率期望|组合数求对数

31 篇文章 0 订阅
13 篇文章 0 订阅

Description

You are one of 2k competitors invited to enter a single elimination tournament. You are ranked
r th in the published rankings. Furthermore, you know that in any match between two players, the one ranked higher will always win.
The only source of uncertainty is the bracket. If every possible tournament bracket is equally likely, determine your expected number of wins in the tournament. Your expected number of wins is the average number of your wins over all possible tournament bracket orderings.

Translation

一次淘汰赛有2k个参赛者。每个参赛者赛前都已经有排名(不会并列),你排在第r名。而且名次靠前的总会战胜名次靠后的。但是比赛的安排是不确定的,比赛安排(即谁与谁比赛)很多等可能的情况。你想知道你在这次淘汰赛平均能有多少次胜利。淘汰赛意味着打赢的一方晋级,输的一方被淘汰出比赛。

Input

The input consists of a single line containing the two space-separated integers k(1k20) and r(1r2k) .

Output

Print, on a single line, your expected number of wins in the tournament, rounded and displayed to exactly five decimal places. The sixth digit after the decimal point of the exact answer will never be 4 or 5 (eliminating complex rounding considerations).
Be careful about very small or very large numbers during intermediate steps.

Sample 1

Sample Input

3 3

Sample Output

1.00000

Sample 2

Sample Input

20 130

Sample Output

11.65203

Solution

队友在virtual contest的时候想的DP,然后没想出来。。输出结果比样例大。

这道题呢。。
假设你能胜 i 次,也就是说至少要打i场比赛,这 i 场比赛的淘汰赛参赛人数是2i1,然后这些人的名次都比你低(也就是说目前这些人都是和你有关的,而不只是和你比赛的 i 个人)。如果不这样,即存在名次比你高的,一定能在另外几场胜出并在某一场和你比赛并战胜你。
那么显然至少能战胜i次的概率为:

Q(i)=C2i12krC2i12k1

也就是说,所有的情况是从 2k1 个人里面随机地选出 2i1 将会和你比赛。但是你要 i 场都胜出,因此是在2kr个人里面选。
因此假设只战胜 i 次(而不是至少)的概率为P(i),那么期望为
ans=iP(i)i=P(1)+2P(2)++nP(n)=[P(1)++P(n)]+[P(2)++P(n)]++P(n)

显然 Q(i)=nj=iP(i) ,那么结果就为
ans=iQ(i)

但是计算组合数嘛。。因为阶乘结果很大然后我们又只需要计算比值,我们可以取对数解决。

Code

#include <cstdio>
#include <cmath>
const int N = 1 << 21;
double logFac[N];
double logC(int n, int m) {
    return logFac[n] - logFac[m] - logFac[n - m];
}

int main() {
    int k, r, i, n, m;
    double ans;

    for (i = 1; i <= (1 << 20); ++ i)
        logFac[i] = logFac[i - 1] + log(i);

    scanf("%d%d", &k, &r);
    n = 1 << k;
    ans = 0;
    for (i = 1; i <= k; ++ i) {
        m = (1 << i) - 1;
        if (n - r < m) break;
        ans += exp(logC(n - r, m) - logC(n - 1, m));
    }
    printf("%.5f\n", ans);

    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值