CF1267G Game Relics
Link
首先显然是先抽卡,抽到一定时间之后直接全买保底。
假如在某个时刻,剩下\(j\)个物品,总价值为\(k\)。
此时进行抽卡直到抽中了一个未买到的物品,就相当于花\((\frac nj-1)\frac x2\)的钱买一个\(\frac kj\)的物品。
我们可以依此判断在一个局面下应该抽卡还是买保底。
设\(f_{j,k}\)表示到达还剩\(j\)个物品,总价值为\(k\)这一局面的概率,这可以用背包求出。然后对每种局面判断策略并计算对答案的贡献即可。
#include<cstdio>
#include<algorithm>
using db=double;
db f[107][10007];int a[107];
int main()
{
int n,x,sum=0;db ans=0;
scanf("%d%d",&n,&x),f[0][0]=1;
for(int i=1;i<=n;++i) scanf("%d",a+i),sum+=a[i];
for(int i=1;i<=n;++i) for(int j=i;j;--j) for(int k=a[i];k<=sum;++k) f[j][k]+=f[j-1][k-a[i]]*j/(n-j+1);
for(int i=1;i<=n;++i) for(int j=1;j<=sum;++j) ans+=f[i][j]*std::min((n+i)*x,j*2)/i;
printf("%.10lf",ans/2);
}