一、题目
二、解法
其他人每个人都是一样的,我们考虑一个人在前
i
i
i场得
j
j
j分的期望
f
[
i
]
[
j
]
f[i][j]
f[i][j],转移如下:
f
[
i
]
[
j
]
=
1
m
−
1
∑
k
=
1
,
k
≠
c
[
i
]
m
f
[
i
−
1
]
[
j
−
k
]
f[i][j]=\frac{1}{m-1}\sum_{k=1,k\not=c[i]}^m f[i-1][j-k]
f[i][j]=m−11k=1,k=c[i]∑mf[i−1][j−k]最后的答案是
(
m
−
1
)
∑
i
=
n
s
−
1
f
[
n
]
[
i
]
+
1
(m-1)\sum_{i=n}^{s-1}f[n][i]+1
(m−1)∑i=ns−1f[n][i]+1,上面的转移很容易用前缀和优化,时间复杂度
O
(
n
2
m
)
O(n^2m)
O(n2m)
#include <cstdio>
#include <iostream>
using namespace std;
#define db double
const int N = 105, M = 1005;
int read()
{
int x=0,flag=1;
char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*flag;
}
int n,m,s,c[N];
db ans,d,f[N][N*M],sum[N*M];
signed main()
{
n=read();m=read();
d=1.0/(m-1);
f[0][0]=sum[0]=1;
for(int i=1;i<=n;i++)
{
s+=(c[i]=read());
for(int j=i;j<=i*m;j++)
{
int l=max(i-1,j-m),r=min((i-1)*m,j-1);
f[i][j]=d*sum[r];
if(l) f[i][j]-=d*sum[l-1];
if(l<=j-c[i] && j-c[i]<=r)
f[i][j]-=d*f[i-1][j-c[i]];
}
sum[i-1]=0;
for(int j=i;j<=i*m;j++)
sum[j]=sum[j-1]+f[i][j];
}
for(int i=n;i<s;i++)
ans+=f[n][i];
printf("%.16lf\n",ans*(m-1)+1);
}