有一个长度为 \(n\) ,初始为 \(0\) 的序列 \(a\).
每次操作可以将一个 \(0\) 变为 \(1\) 或 \(-1\), 并满足 \(1\) 和 \(-1\) 不相邻.
最后无法操作的一方为输家.
特殊地, 若最后整个序列全部变为 \(1\) 或 \(-1\), 则后手胜.
由玩家选择先手/后手, 每次输入一个二元组 \((p,ty)\), 表示将 \(a_p\) 变为 \(ty\), 每次输出一个二元组 \((p,ty)\), 表示将 \(a_p\) 变为 \(ty\).
制定策略, 确保我方能胜利.
\(1 \le n \le 2^10\).
主要思想 : 分奇偶讨论.
最终空格数量 | 奇数 | 偶数 | 0 |
---|---|---|---|
胜者 | 先手 | 后手 | 后手 |
左右端点粒子 | 不同 | 相同 | 相同 |
最终空格数量 | 奇数 | 偶数 | 0 |
---|---|---|---|
胜者 | 后手 | 先手 | 后手 |
左右端点粒子 | 不同 | 相同 | 相同 |
由上表可知, 我们可以通过控制左右端点粒子是否相同来控制胜负情况.
为了控制左右端点是否相同, 我们需要让对手先改变其中一个端点上的粒子, 再在另一个端点填上对应的粒子.
这样我们可以先排除左右两端点, 然后进行一个类似递归的子任务. (当然实现过程不是递归.)
具体的实现过程需要分奇偶讨论, 然后制定策略, 使得在每个阶段, 都让对手先改变端点上的粒子, 或者保持所有粒子一致.
若选择先手, 则后手每次都可以在序列的轴对称位置填上一个相同的数, 使左右端点粒子相同, 这样必输.
所以我们选择后手, 每次在序列的轴对称位置填上与对手相同的数, 这样左右端点粒子就一定是相同的.
若选择先手, 若第一步不选择中点, 则会落得与 \(n\) 为偶数时一样的下场; 若第一步选择中点, 对手可以紧贴这我们选择的点来填相同的点, 如果一直填下去, 对手就赢了, 所以我们被迫要在端点填上一个与原来不同的点, 这时对手又可以在对应位置填上一个和我们不同的点, 还是对手赢.
所以我们还是选择后手, 维护一个被改变了的区间 \([l,r]\), 且 \(l,r\) 轴对称, 每次在区间里填点或者紧贴着区间边界填点. 若对手在端点上填了一个与原来不同的点, 我们就在轴对称位置填上一个与它不同 (与原来相同) 的点.
#include<bits/stdc++.h>
using namespace std;
const int _=2e3+7;
int n,a[_],rev[_],tag,p,ty,lc,rc;
bool fl;
bool judge(int i){
if(a[i]!=0) return 0;
if(a[i+1]==1&&a[i-1]==-1) return 0;
if(a[i+1]==-1&&a[i-1]==1) return 0;
return 1;
}
bool check(){
for(int i=1;i<=n;i++)
if(judge(i)) return 1;
return 0;
}
bool find(){
for(int i=lc;i<=rc;i++)
if(judge(i)){
if(a[i-1]!=0) a[i]=a[i-1];
else if(a[i+1]!=0) a[i]=a[i+1];
else a[i]=tag;
cout<<i<<‘ ‘<<a[i]<<endl;
return 1;
}
return 0;
}
int main(){
#ifndef ONLINE_JUDGE
//freopen("x.in","r",stdin);
#endif
memset(a,0,sizeof(a));
cin>>n>>ty;
cout<<1<<endl;
for(int i=1;i<=n;i++) rev[i]=n-i+1;
if(n==1){
cin>>p>>ty;
return 0;
}
else if(n==2){
cin>>p>>ty;
if(p==1) cout<<2<<‘ ‘<<ty<<endl;
else cout<<1<<‘ ‘<<ty<<endl;
return 0;
}
else if(n==3){
cin>>p>>ty;
if(p==1) cout<<2<<‘ ‘<<ty<<endl;
else cout<<1<<‘ ‘<<ty<<endl;
cin>>p>>ty;
return 0;
}
else if(!(n%2)){
while(1){
cin>>p>>ty;
a[p]=ty;
a[rev[p]]=ty;
cout<<rev[p]<<‘ ‘<<ty<<endl;
if(!check()) return 0; // 若游戏结束, 需立刻结束程序(题目要求)
}
}
else{
lc=n/2; rc=n/2+2;
cin>>p>>ty; tag=ty;
if(rev[p]==p){
a[p]=ty; a[lc]=ty;
cout<<lc<<‘ ‘<<ty<<endl;
if(lc>1){ lc--; rc++; }
while(1){
cin>>p>>ty;
a[p]=ty;
if(p>=lc&&p<=rc){
find();
if(a[lc]!=0||a[rc]!=0){
if(lc>1){ lc--; rc++; }
}
}
else{
a[rev[p]]=-ty;
cout<<rev[p]<<‘ ‘<<-ty<<endl;
lc=min(p,rev[p]);
rc=max(p,rev[p]);
cin>>p>>ty;
break;
}
if(!check()) return 0;
}
}
while(1){
a[p]=ty;
if(p>=lc&&p<=rc) find();
else{
a[rev[p]]=-ty;
cout<<rev[p]<<‘ ‘<<-ty<<endl;
lc=min(p,rev[p]);
rc=max(p,rev[p]);
}
if(!check()) return 0;
cin>>p>>ty;
}
}
}
「解题报告」[luoguP6585]中子衰变 (交互题 分类讨论)
原文:https://www.cnblogs.com/BruceW/p/13149523.html