ICPC Pacific Northwest Regional Contest 2016 - Tournament Wins(组合数学求期望)

You are one of 2^k competitors invited to enter a single elimination tournament. You are rankedrth in the published rankings. Furthermore, you know that in any match between two players, theone 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 theaverage number of your wins over all possible tournament bracket orderings.

Input

The input consists of a single line containing the two space-separated integers k (1 ≤ k ≤ 20) andr (1 ≤ r ≤ 2^k).

Output

Print, on a single line, your expected number of wins in the tournament, rounded and displayed toexactly five decimal places. The sixth digit after the decimal point of the exact answer will neverbe 4 or 5 (eliminating complex rounding considerations). 

Be careful about very small or very large numbers during intermediate steps.

样例输入1复制

3 3

样例输出1复制

1.00000

样例输入2复制

20 130

样例输出2复制

11.65203

题目链接:点击查看

题目大意:现在有 1 << k 个人参加比赛,赛制是两两淘汰赛,也就是说共进行 k 轮比赛,每个人的能力都有一个严格的排行,两个人比赛的话,排行靠前的人一定会获胜,现在题目告诉了你的排行,问赢得比赛的期望是多少

题目分析:概率问题。。我们可以枚举 i ,意思是能够连赢 i 轮的概率,对于每个 i ,概率相加就是答案了

因为一共有 2^k 个人,那么有 2^k-1 个人作为对手,因为你的排行为 r ,所以比你菜的人有 2^k - r 个人,所以能够连赢 i 局的情况,就是\frac{C(2^k-r,2^i-1)}{C(2^k-1,2^i-1)},也就是说从比你菜的人里面选 2^i-1 的方案数,除以从所有对手里面选 2^i-1 人的方案数,就是能够连赢 i 场的概率了

至于实现,因为阶乘的话数会非常大,所以我们可以取个 log ,换句话说:log(\frac{C(n1,m1)}{C(n2,m2)})=log(C(n1,m1))-log(C(n2,m2))

同理\tiny logC(n,m)=log(\frac{fac[n]}{fac[m]fac[n-m]})=log(fac[n])-log(fac[m])-log(fac[n-m])

\small logfac[n]=log(1*2*...*n)=log(1)+log(2)+...+log(n)

随便取一个底,然后都取log,最后再用pow还原就可以控制精度问题了

代码:
 

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
using namespace std;

typedef long long LL;

typedef unsigned long long ull;

const int inf=0x3f3f3f3f;

const int N=(1<<20)+100;

double fac[N];

void init()
{
	fac[0]=log2(1);
	for(int i=1;i<N;i++)
		fac[i]=fac[i-1]+log2(i);
}

double C(int n,int m)
{
	if(m>n)
		return -1e10;
	return fac[n]-fac[m]-fac[n-m];
}

int main()
{
#ifndef ONLINE_JUDGE
//  freopen("input.txt","r",stdin);
//  freopen("output.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);
	init();
	int k,r;
	scanf("%d%d",&k,&r);
	int n=(1<<k)-1;//总人数 
	int t=(1<<k)-r;//比自己弱的人数
	double ans=0;
	for(int i=1;i<=k;i++)
	{
		int d=(1<<i)-1;
		ans+=pow(2,C(t,d)-C(n,d));
	}
	printf("%.5f\n",ans);







    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/106892395