题目翻译
有两个人 A 和 B 在玩一个游戏,这个游戏的棋盘是一个长度为 n n n 的数组,每个格子标号为 1 , 2 , … , n 1,2,\ldots,n 1,2,…,n,里面有一部分格子已经放好了 1 1 1 或 0 0 0,两人轮流选择一个空格子并在里面放置 0 0 0 或 1 1 1,但是不能有任何两个相邻的格子同时为 1 1 1 或 0 0 0,问这个游戏先手必胜还是后手必胜。
题解
我们发现对于一段连续的空格子,他两端的 0 , 1 0,1 0,1 值会影响这一段的结果,而且每一空段相互独立。讨论一下:
- 两端同为 1 1 1 或者 0 0 0。假设这一段长度为奇数,那么我们两个人可以轮流填上 0 , 1 0,1 0,1,显然先手会填完最后一个。如果这一段长度为偶数,两个人还是轮流填上 0 , 1 0,1 0,1,但是剩下一个格子的时候,那个人也没法填了,换句话说,偶数与奇数的情况是相等的,无论如何先手都必胜。
- 两端不同,一个 1 1 1 一个 0 0 0。这种情况可以转化为两端相同的情况,但是我要花费一次才能到达这种情况,所以显然先手必败。
那么对于第一种情况,先手与后手会交换顺序,而第二种情况不改变先后顺序,所以我们令第一种情况得到的值为 1 1 1,第二种情况的值为 0 0 0,跟 Nim 游戏是一样的,异或起来即可。
//C Nim
#include<bits/stdc++.h>
#define int long long
#define mid ((l+r)>>1)
#define fir first
#define sec second
#define lowbit(i) (i&(-i))
using namespace std;
const int N=5e5+5;
const int inf=1e18;
struct edge{int to,nxt,l;};
struct nim{int x,y;}a[N];
bool cmp(nim x,nim y){return x.x<y.x;}
inline int read(){
char op=getchar();
int w=0,s=1;
while(op<'0'||op>'9'){
if(op=='-') s=-1;
op=getchar();
}
while(op>='0'&&op<='9'){
w=(w<<1)+(w<<3)+op-'0';
op=getchar();
}
return w*s;
}
int ans=0;
signed main(){
int n=read(),m=read();
for(register int i=1;i<=m;i++){
a[i].x=read(),a[i].y=read();
}
if(m==0) ans^=(n%2);
else{
sort(a+1,a+m+1,cmp);
for(register int i=1;i<m;i++){
if(a[i].x==a[i+1].x-1) continue;
if(a[i].y==a[i+1].y) ans^=1;
else ans^=0;
}
if(a[m].x!=n) ans^=(n-a[m].x);
if(a[1].x!=1) ans^=(a[1].x-1);
}
if(!ans) printf("Aoki");
else printf("Takahashi");
}