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