[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;
}

浙公网安备 33010602011771号