#交互,鸽笼原理#CF1776C Library game

发布时间 2023-10-27 00:52:24作者: lemondinosaur

题目

有一个长度为 \(m\) 的书架,以及 \(n\) 个长度 \(a_1,a_2,\dots,a_n\)

Alessia 和 Bernardo 从书架上取书。每次由 Alessia 选择一个之前没选过的 \(i\)

并选择一个长度为 \(a_i\) 的区间,需要保证这个区间内的书全都没有被取过。然后 Bernardo 从区间内任意拿走一本书。

Bernardo 的目标是让 Alessia 某一步没有区间可选。输出谁赢,并交互构造方案。

\(n\leq 100,m\leq 5000\)


分析

引理:Alessia获胜当且仅当 \(a\) 降序排序后不存在 \(a_i>\lfloor\frac{m}{i}\rfloor\)

因为如果不存在,那么根据鸽笼原理每次必有一个区间长度大于等于 \(\lfloor\frac{m}{i}\rfloor\),必可选

否则若 \(\exists k,a_k>\lfloor\frac{m}{k}\rfloor\),让区间长度为 \(a_{1\sim k}\) 的区间选择的位置为 \(a_k\) 的倍数,其它任选。

因为 \(k>\lfloor\frac{m}{a_k}\rfloor\),必有一个位置是重复的


代码

#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
const int N=5011;
int n,m,s[N],a[N],v[N],o;
int iut(){
	int ans=0; char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=ans*10+c-48,c=getchar();
	return ans;
}
int main(){
	n=iut(); m=iut();
	for (int i=1;i<=n;++i) a[i]=iut();
	sort(a+1,a+1+n),reverse(a+1,a+1+n);
	for (int i=1;i<=n;++i)
	if (a[i]>m/i){
		o=a[i];
		break;
	}
	if (!o){
		printf("Alessia\n"),fflush(stdout);
		for (int i=1;i<=n;++i){
			for (int j=1;j<=m;++j) s[j]=s[j-1]+v[j];
			for (int j=a[i];j<=m;++j)
			if (s[j]==s[j-a[i]]){
				printf("%d %d\n",a[i],j-a[i]+1);
				fflush(stdout);
				break;
			}
			v[iut()]=1;
		}
	}else{
		printf("Bernardo\n"),fflush(stdout);
		for (int i=1;i<=n;++i){
			int len=iut(),l=iut();
			if (len>=o) printf("%d\n",(l+o-1)/o*o);
			    else printf("%d\n",l);
			fflush(stdout);
		}
	}
	return 0;
}