CF1267G Game Relics

CF1267G\(\mathbf{} \begin{Bmatrix} \frac{{\Large CF1267G} }{{\color{Red}\Large Solution} }\mathbf{} {No.21} \end{Bmatrix}\times{}\) NeeDna

题解用了 Yizhixiaoyun 的式子和 wangzihan_ 的部分证明,感谢两位神犇!

题意:

\(n\) 种圣物,每个的价值为 \(c_{i}\),现在有两种操作,一种是直接买,还有一种是抽卡,花费 \(x\) 代价随机抽出一张,如果是已经有的,那么就返还 $\dfrac{x}{2} $ 代价,否者抽出新的,问最优策略下的获得所有圣物期望代价。

题解:

先确定最优策略是什么,思考一下很明显是先抽后买,感性理解就是越到后面越难抽出新东西出来,但也让我们来理性证明一下。

证明:首先购买一定是买当前价值最小的圣物。考虑相邻两次操作,如果先购买再抽奖,注意到本题的随机规则和决策是无关的,那么我们可以当成,在游戏开始之前,每次抽的结果就已经确定了,那么分情况讨论:

  1. 如果下一次抽奖抽到的就是,最小值,则如果先买再抽,我们就白买了。

  2. 如果下一次抽奖抽到的不是,最小值,则交换两次操作不影响结果。

那发现就是有关价值的决策,考虑决策代价:

因为 \(Q_{期望}=\sum w_{代价}\times p_{概率}\) 所以分开计算。

\(f_{i,j}\) 为抽了 \(i\) 次,抽出的代价为 \(j\) 的次数,那么 \(f\) 数组明显可以用背包来做,可以求出次数,那么除以总可能那么概率就是 \(\dfrac{f_{i,j}}{C_{n}^{i}}\) 了。

因为有抽和买两种代价,思考获得下一个圣物的期望代价。如果我们已经有了 \(i\) 张卡,易得抽一张新卡概率为 \(\dfrac{n-i}{n}\),则需要抽 \(\dfrac{n}{n-i}\) 次。

除了最后一次之外,其他的次数都可以让我们获得 \(\dfrac{x}{2}\) 的回馈,最后一次消耗 \(x\) 获得新卡,则期望消耗为:

\[(\frac{n}{n-i}+1) \times \frac{x}{2} \]

接着寻找抽卡与买的分界线。考虑把所有直接购买的花费均摊到每次之中。令已有的卡价值为 \(w_{have}\),总价值为 \(sum\),则单次消耗为 \(\dfrac{sum-w_{have}}{n-i}\),转换策略判断条件为:

\[\frac{sum-w_{have}}{n-i} < (\frac{n}{n-i}+1) \times \frac{x}{2} \]

代码里直接概率乘上两个的最小值即可,所有可能性加起来自动就是答案,很巧妙。

ac code:

#include<bits/stdc++.h>
using namespace std;
const int N=1e2+10,M=1e4+10;
int n,x,a[N];
double c[N][N],f[N][M],ans;
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>n>>x;
	for(int i=1;i<=n;i++) cin>>a[i];
	c[0][0]=f[0][0]=1;
	for(int i=1;i<=n;i++){c[i][0]=1;
		for(int j=1;j<=n;j++){
			c[i][j]=c[i-1][j-1]+c[i-1][j];
		}
	}int sum=0;
	for(int i=1;i<=n;i++){
		for(int j=i-1;j>=0;j--){
			for(int k=sum;k>=0;k--){
				f[j+1][k+a[i]]+=f[j][k];
			}
		}
		sum+=a[i];
	}
	for(int i=0;i<=n-1;i++){
		for(int j=0;j<=sum;j++){
			ans+=min(1.0*(sum-j)/(n-i),x*(1.0*n/(n-i)+1)/2)*f[i][j]/c[n][i]; 
		}
	}
	cout<<fixed<<setprecision(8)<<ans;
	return 0;
}

posted @ 2025-05-31 22:13  NeeDna  阅读(13)  评论(0)    收藏  举报