CF1267G Game Relics

CF1267G Game Relics

\(n\) 个物品,你可以进行下面两种操作:

  • 花费 \(c_i\) 元购买第 \(i\) 个物品。

  • 花费 \(x\) 元抽奖,随机获得一个物品 \(i\)。若你已经拥有第 \(i\) 个物品,则你本次抽奖的花费改为 \(\dfrac{x}{2}\) 元。

求获得所有物品的期望最小花费。

\(1 \leq n \leq 100\)\(1 \leq x \leq c_i \leq 10000\)\(\sum\limits_{i=1}^{n} c_i \leq 10000\)

首先我们有如下的观察:

性质 \(1\):如果选择抽奖,则会一直选择抽奖,直到抽到新的物品为止。

证明显然,考虑若抽奖在当前状态下是最优决策,则没有抽到新的物品时状态不变,继续抽奖仍然是最优决策。

此时我们不妨设已经拥有了 \(k\) 个物品,则抽到一个新物品的期望花费为 \(\sum\limits_{i=0}^{\infty} (\dfrac{k}{n})^i \times \dfrac{n-k}{n} \times (\dfrac{i}{2} + 1) \times x\),经过计算可以化简为 \(\dfrac{x}{2} \times (1 + \dfrac{n}{n-k})\)。此时第二个操作等价于花费 \(\dfrac{x}{2} \times (1 + \dfrac{n}{n-k})\) 元随机获得一个当前没有的物品 \(i\)。通过这一点,我们可以得出新的观察:

性质 \(2\):一定先抽若干次奖,再购买剩下的所有物品。

感性理解一下,越往后抽奖的花费越高,而购买物品的花费是固定的,显然先抽奖再买物品更优。

此时我们发现,购买物品的顺序没有影响,可以看成随机购买一个当前没有的物品。假设当前已经拥有的 \(k\) 个物品价值和为 \(s\) 元,\(n\) 个物品的总价值和为 \(S\) 元,则操作可以变为下面的形式:

  • 花费 \(\dfrac{S-s}{n-k}\) 元随机获得一个当前没有的物品 \(i\)

  • 花费 \(\dfrac{x}{2} \times (1 + \dfrac{n}{n-k})\) 元随机获得一个当前没有的物品 \(i\)

显然每步都可以将两者取最小值,即:

  • 花费 \(\min(\dfrac{S-s}{n-k},\dfrac{x}{2} \times (1 + \dfrac{n}{n-k}))\) 元随机获得一个当前没有的物品 \(i\)

我们考虑设计 \(dp_{k,s}\) 表示在 \(k\)\(s\) 的情况下拥有的物品方案数,则答案可以简单的看作每一步的期望和,也就是:

\[\sum\limits_{k=0}^{n-1} \sum\limits_{s=0}^{S} \dfrac{dp_{k,s}}{C_n^k} \times \min(\dfrac{S-s}{n-k},\dfrac{x}{2} \times (1 + \dfrac{n}{n-k})) \]

结束了。

复杂度 \(O(n^2S)\)

#include<iostream>
#include<cstdio>
using namespace std;
int n,S,c[110]; 
double x,fact[110],dp[110][10010];
double calc(int k,int s){
	return min(1.0*(S-s),x*(2*n-k)/2)/(n-k);
}
int main(){
	scanf("%d %lf",&n,&x);
	fact[0]=1;
	for(int i=1;i<=n;i++){
		scanf("%d",&c[i]);
		S+=c[i];
		fact[i]=fact[i-1]*i;
	}
	dp[0][0]=1;
	for(int i=1;i<=n;i++){
		for(int k=i;k>=1;k--){
			for(int s=S;s>=c[i];s--){
				dp[k][s]+=dp[k-1][s-c[i]];
			}
		}
	}
	double ans=0;
	for(int k=0;k<n;k++){
		for(int s=0;s<=S;s++){
			ans+=dp[k][s]*calc(k,s)*fact[k]*fact[n-k]/fact[n];
		}
	}
	printf("%.15lf",ans);
	return 0;
}
posted @ 2025-10-27 19:46  Oken喵~  阅读(2)  评论(0)    收藏  举报