题目链接:http://codeforces.com/problemset/problem/261/B
题意:有一个长度为P的桌子。有n个人,第i个人坐在桌子边的话需要占得长度为ai。n个人站成一队,从队头开始坐。到某个人时,桌子剩下的部分不够这个人坐的时候停止。这时,有x个人坐下。n!种排队的方式每种都有一个x值。求x的平均值。
思路:f[i][j][k]表示取j个数和为i以k作为分隔,即i再加上第k个数就会超。那么最后只要枚举k,然后i枚举[p+1-ak,p]即可。
double fac[55],f[55][55][55];
int a[55],n,p;
int main()
{
int i,j,k,x=0;
fac[0]=1;
for(i=1;i<=50;i++) fac[i]=fac[i-1]*i;
scanf("%d",&n);
for(i=1;i<=n;i++) scanf("%d",&a[i]),x+=a[i];
scanf("%d",&p);
if(x<=p)
{
printf("%d\n",n);
return 0;
}
for(i=1;i<=n;i++) f[0][0][i]=1;
for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(i!=j)
{
for(k=n;k>=1;k--) for(x=p;x>=0&&x>=a[i];x--)
{
f[x][k][j]+=f[x-a[i]][k-1][j];
}
}
double ans=0;
for(i=1;i<=n;i++)
{
if(a[i]>p) a[i]=p+1;
for(x=p+1-a[i];x<=p;x++) for(k=1;k<=n;k++)
{
ans+=f[x][k][i]*fac[k]*fac[n-k-1]*k;
}
}
ans/=fac[n];
printf("%.7lf\n",ans);
return 0;
}