NOIP2023模拟12联测33 游戏

文章描述了一个博弈问题,学生和老师在多个实验室中进行游戏,学生的目标是让老师抓到的人数最少,老师的目标是抓到最多。通过二分法求解,找出使老师抓到期望人数的最大值,同时保证学生有策略应对。

题目大意

nnn个物理实验室,第iii个实验室有aia_iai个人,他们全都在打游戏。

同学AAA可以选择进入一间实验室iii,然后让其中的所有aia_iai个人停止打游戏。

然后老师BBB可以选择进入一间实验室jjj,然后抓住其所有在打游戏的人。

同学AAA的目标是让老师BBB抓到的人最少,而老师的目标是抓到最多的人。

老师BBB在决策时无法知道同学AAA进入过哪个实验室。

两人都选择最优策略,问老师期望可以抓到多少人,注意两个人的决策都是可以基于概率的。

也就是说,你要找到一个mmm,使得无论老师怎么操作,总存在同学的一种方案使得被抓的人数期望≤m\leq mm;同时无论同学怎么操作,总存在老师的一种方案使得被抓的人数期望≥m\geq mm

输出被抓的期望人数,相对误差在10−910^{-9}109即视为正确。

1≤n≤30,0≤ai≤401\leq n\leq 30,0\leq a_i\leq 401n30,0ai40


题解

二分答案midmidmid,我们只关注同学能否使得被抓人数≤mid\leq midmid

那么,ai≤mida_i\leq midaimid的实验室就无关紧要了,我们只关注ai>mida_i>midai>mid的实验室。设同学AAApip_ipi的概率进入实验室iii,那么如果老师选择进这个实验室,则期望被抓的人数为(1−pi)×ai(1-p_i)\times a_i(1pi)×ai

所以,对于任意的aia_iai,都要满足(1−pi)×ai≤mid(1-p_i)\times a_i\leq mid(1pi)×aimid,那么我们可以求出每个pip_ipi的下界,并加起来看看是否超过111。如果超过111的话,因为pip_ipi的总和要为111,那就存在pip_ipi不能满足(1−pi)×ai≤mid(1-p_i)\times a_i\leq mid(1pi)×aimid,那么midmidmid就不可取;否则,midmidmid就是可取的。

假设二分得出的值为ansansans,那么我们来证明ansansans就是答案。

上面已经证明了同学能使期望被抓的人数≤m\leq mm,下面来证明老师能使期望被抓的人数≥m\geq mm

假设有kkk个大于ansansansaia_iai,则由(1−pi)×ai=ans(1-p_i)\times a_i=ans(1pi)×ai=ans可得pi=ai−ansaip_i=\dfrac{a_i-ans}{a_i}pi=aiaians,于是∑pi=∑ai−ansai=m−ans∑1ai\sum p_i=\sum \dfrac{a_i-ans}{a_i}=m-ans\sum\dfrac{1}{a_i}pi=aiaians=mansai1ans=m−1∑1aians=\dfrac{m-1}{\sum\frac{1}{a_i}}ans=ai1m1

给出老师的一种策略:以1aj(∑1ai)\dfrac{1}{a_j(\sum\frac{1}{a_i})}aj(ai1)1的概率选择进入第jjj个实验室,那么其最坏能抓到的人数为

min⁡t=1n(∑j≠t1aj(∑1ai)×aj)=m−1∑1ai=ans\min\limits_{t=1}^n(\sum\limits_{j\neq t}\dfrac{1}{a_j(\sum\frac{1}{a_i})}\times a_j)=\dfrac{m-1}{\sum\frac{1}{a_i}}=anst=1minn(j=taj(ai1)1×aj)=ai1m1=ans

其中ttt枚举的是同学选择进入的房间。

那么,这样就可以证明ansansans就是答案。

时间复杂度为O(nlog⁡v)O(n\log v)O(nlogv),其中vvvansansans的值域。

code

#include<bits/stdc++.h>
using namespace std;
const long double eps=1e-12;
int n,mx,a[35];
long long ans;
bool check(long double k){
	long double re=0;
	for(int i=1;i<=n;i++){
		if(a[i]<=k) continue;
		re+=1-k/a[i];
	}
	if(re>1) return 0;
	return 1;
}
int main()
{
//	freopen("game.in","r",stdin);
//	freopen("game.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		mx=max(mx,a[i]);
	}
	long double l=0,r=mx,mid;
	while(r-l>=eps){
		mid=(l+r)*0.5;
		if(check(mid)) r=mid;
		else l=mid;
	}
	printf("%.12Lf",r);
	return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值