Codeforces Round #333 (Div. 1) C

Kleofáš and the n-thlon

        概率dp。dp求的东西是除了自己以外,其他人得到各种分数的概率,状态转移见代码。然后就可以算出其他人超过自己的概率了。根据这个概率,结合组合数,计算期望。由于精度问题,要先取对数。还要注意概率为0,1的情况。


#include <bits/stdc++.h>
using namespace std;

#define ll long long

double dp[2][100010];

int a[110];

int main(){
	int n,m;	//比赛 人 
	cin>>n>>m;
	int sum=0;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		sum+=a[i];
	}
	
	dp[0][0]=1;
	int MAX;
	for(int i=1;i<=n;i++){
		MAX=m*i;
		for(int j=0;j<=MAX;j++){
			dp[i&1][j]=0;
		}
		double tmp=0;
		for(int j=0;j<=MAX;j++){
			tmp+=dp[(i-1)&1][j-1];
			if(j>m){
				tmp-=dp[(i-1)&1][j-m-1];
			}
			dp[i&1][j]+=tmp;
			if(j>=a[i])dp[i&1][j]-=dp[(i-1)&1][j-a[i]];
		}
	}
	
	double smaller=0;
	double total=0;
	
	if(m==1){
		cout<<1<<endl;
		return 0;
	}
	
	for(int i=1;i<=MAX;i++){
		if(i<sum){
			smaller += dp[n&1][i];
		}
		total += dp[n&1][i];
	}
	
	double p = smaller/total;
	
	if(p==0){
		cout<<1<<endl;
		return 0;
	}else if(p==1){
		cout<<m<<endl;
		return 0;
	}

	double curP = log2(1-p)*(m-1);
	
	double ans = 0;
	double C = 0;
	for(int i=1;i<=m;i++){
		ans+=pow(2,curP+C+log2(i));
		curP+=log2(p);
		curP-=log2(1-p);
		C+=log2(m-i);
		C-=log2(i);
	}
	
	printf("%.10f\n",ans);
	return 0;
}


你可能感兴趣的:(dp,codeforces)