把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

【CF1267G】Game Relics(期望)

题目链接

  • \(n\) 个物品,第 \(i\) 个物品直接购买的价格为 \(c_i\)
  • 除了直接购买,你还可以以 \(x\) 的代价等概率抽取一件物品,如果已经获得过抽到的物品则退还 \(\frac x2\)
  • 求获得所有物品的最小期望花费。
  • \(1\le n\le100\)\(c_i\ge x\)\(\sum c_i\le 10^4\)

先抽卡再购买

考虑我们一定是选择先抽卡再购买。

因为假如我们先购买再抽卡,只会让抽取到新物品的概率变小,而抽重复退还的 \(\frac x2\) 又比购买花费更小,因此肯定不优。

假设当前已经有 \(i\) 个物品,拥有的物品价值和为 \(j\)(并设所有物品价值总和为 \(t\))。

则,此时抽取出一个新物品的概率为 \(\frac{n-i}n\),也就是说期望次数为 \(\frac n{n-i}\),那么期望代价就是 \((\frac n{n-i}+1)\frac x2\)。而剩余物品总价值为 \(t-j\),也就是说抽取出的物品的期望价值为 \(\frac{t-j}{n-i}\)

显然,如果期望代价比期望价值更大,那么我们肯定不会再选择去抽卡,而是直接购买了。

实际上可以利用这两个式子再次证明开始的结论:\((\frac n{n-i}+1)\frac x2 > \frac{t-j}{n-i}\Leftrightarrow (2n-i)\frac x2>t-j\),则随着 \(i\) 的增大,左式减少 \(\frac x2\),右式减少 \(c_{k}\),因为右式减少得更多,不等式必然依旧成立。

随机购买

如果直接考虑什么时候转成全部购买,需要保证这一次抽卡代价更大,且上一次抽卡代价更小,比较麻烦,复杂度偏高。

所以需要再来一个转化,就是即便确定了要直接购买了,我们不一次性全买下来,而是随机去一个一个购买,容易发现这与原问题等价。

现在既然完全随机了,那么出现任意一类局面的概率就可以直接计算了。

仍然假设当前已经有 \(i\) 个物品,拥有的物品价值和为 \(j\),可以简单背包求出每一类局面的个数。

而这类局面的期望代价就是先前提到的两种期望代价的较小值,即 \(\min\{(\frac n{n-i}+1)\frac x2,\frac{t-j}{n-i}\}\)

由于每种局面出现概率都是 \(\frac1{C_n^i}\),对同一类局面可以直接给答案加上贡献乘上这类局面种数。

代码:\(O(n^2\sum c_i)\)

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Rg register
#define RI Rg int
#define Cn const
#define CI Cn int&
#define I inline
#define W while
#define N 100
#define V 10000
#define DB double
using namespace std;
int n,x,c[N+5];DB g[N+5][V+5],C[N+5][N+5];
int main()
{
	RI i,j,k;for(scanf("%d%d",&n,&x),i=1;i<=n;++i) scanf("%d",c+i);
	for(C[0][0]=i=1;i<=n;++i) for(C[i][0]=j=1;j<=i;++j) C[i][j]=C[i-1][j-1]+C[i-1][j];//预处理组合数
	DB t=0;for(g[0][0]=i=1;i<=n;t+=c[i++]) for(j=i-1;~j;--j) for(k=t;~k;--k) g[j+1][k+c[i]]+=g[j][k];//背包预处理每种局面数
	DB ans=0;for(i=0;i^n;++i) for(j=0;j<=t;++j) ans+=min((1.0*n/(n-i)+1)*x/2,(t-j)/(n-i))*g[i][j]/C[n][i];//枚举局面计算期望
	return printf("%.12lf\n",ans),0;
}
posted @ 2022-01-23 16:33  TheLostWeak  阅读(106)  评论(3编辑  收藏  举报