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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章