[SWERC 2022] Library game

[SWERC 2022] Library game

有点意思啊。

假设第 \(i\) 天游戏未能结束,则之前 \(i-1\) 天 Bernardo 取得的应当是 \(i-1\) 本不同的书,还剩 \(m-i+1\) 个位置被分成 \(i\) 块。假设当天的通行证长度为 \(y_i\),则 Alessia 能够继续的条件是存在一块的长度 \(\geq y_i\)。

条件转写成最长块的长度 \(\geq y_i\)。显然我们有最长块的长度 \(\geq \lceil \dfrac{m-i+1}{i} \rceil = \lfloor \dfrac{m}{i} \rfloor\)。

我们猜测 Alessia 能够获胜的充要条件是 \(y_i \leq \lfloor \dfrac{m}{i} \rfloor\)。

此时我们发现 \(\lfloor \dfrac{m}{i} \rfloor\) 是呈下降趋势的,所以 \(x\) 要降序排序。

考虑 Alessia 必胜时的策略,由上面的分析,Alessia 无论如何安排,必有合法方案。


接下来考虑 Bernardo 的策略,考虑令降序排序后的 \(X\) 序列为 \(Y\),且有 \(y_a > \lfloor \dfrac{m}{a} \rfloor\)。据此,我们可以得到 \(a > \lfloor \dfrac{m}{y_a} \rfloor\),也就是说 \(m\) 以内 \(y_a\) 的倍数个数小于 \(a\)。

同时,我们存在至少 \(a\) 个 \(x_i \geq y_a\),则能够造出 \(a\) 个 \(y_a\) 的倍数。而留给 \(y_a\) 的倍数不到 \(a\) 个,则必有一个 \(y_a\) 的倍数出现两次。

//Ad astra per aspera
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,y[110];
bool flag[5010];
int len[5010];
void Alessia(){
	cout<<"Alessia"<<endl;
	for(int i=1;i<=n;i++){
		int len=0;
		for(int j=m;j>=1;j--){
			len++;
			if(flag[j]){
				len=0;
			}
			if(len>=y[i]){
				cout<<y[i]<<" "<<j<<endl;
				break;
			}
		}
		int pos;
		cin>>pos;
		flag[pos]=true;
	}
}
void Bernardo(int a){
	cout<<"Bernardo"<<endl;
	for(int i=1;i<=n;i++){
		int len,l;
		cin>>len>>l;
		int r=l+len-1;
		int pos=l;
		for(int j=l;j<=r;j++){
			if(j%y[a]==0){
				pos=j;
			}
		}
		cout<<pos<<endl;
		flag[pos]=true;
	}
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>y[i];
	} 
	sort(y+1,y+n+1);
	reverse(y+1,y+n+1);
	for(int i=1;i<=n;i++){
		if(y[i]>m/i){
			Bernardo(i);
			return 0;
		}
	}
	Alessia();
	return 0;
}
posted @ 2026-05-15 16:47  Oken喵~  阅读(12)  评论(0)    收藏  举报