您的位置:首页 > 其它

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

2017-12-09 20:31 1051 查看

Description

You are one of 2k competitors invited to enter a single elimination tournament. You are ranked

rth 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(1≤k≤20) and r(1≤r≤2k).

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场比赛的淘汰赛参赛人数是2i−1,然后这些人的名次都比你低(也就是说目前这些人都是和你有关的,而不只是和你比赛的i个人)。如果不这样,即存在名次比你高的,一定能在另外几场胜出并在某一场和你比赛并战胜你。

那么显然至少能战胜i次的概率为:

Q(i)=C2i−12k−rC2i−12k−1

也就是说,所有的情况是从2k−1个人里面随机地选出2i−1将会和你比赛。但是你要i场都胜出,因此是在2k−r个人里面选。

因此假设只战胜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
;
double logC(int n, int m) {
return logFac
- 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: