不得不说SG函数真的神奇。
链接:http://codeforces.com/gym/101908/problem/B
题目大意:一个100*100的棋盘上有n个棋子,每个棋子只能向左,向右,向左上移动k个单位,两个人轮流博弈,问是否可以最后赢。
题目思路:
一个状态SG【x】【y】=mex{ sg【i-k】【j】,sg【i】【j-k】,sg【i-k】【j-k】};
然后异或起来,特殊情况就是上来第一步就赢了的要特殊判断。还有就是不能往一些必输点跳。
一个数的SG值一定是它的后继中的非必败态,或者是这个位置不知道是否为胜或败的状态(引用CSDN大佬的话)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int sg[505][505];
int vis[10500];
void getsg()
{
for(int i=1;i<=100;i++){
for(int j=1;j<=100;j++){
if(i==j)continue;
memset(vis,0,sizeof(vis));
for(int k=1;k<=i-1;k++){
if(i-k!=j)vis[sg[i-k][j]]=1;
}
for(int k=1;k<=j-1;k++){
if(j-k!=i)vis[sg[i][j-k]]=1;
}
for(int k=1;k<min(i,j);k++){
vis[sg[i-k][j-k]]=1;
}
for(int k=0;;k++)
{
if(!vis[k])
{
sg[i][j]=k;
break;
}
}
}
// cout<<i<<endl;
}
}
int main()
{
getsg();
int n;
cin>>n;
int ans=0;
bool ff=1;
for(int i=1;i<=n;i++){
int x,y;
cin>>x>>y;
if(x==y)ff=0;
ans^=sg[x][y];
}
if(ans||!ff){
cout<<"Y"<<endl;
}
else{
cout<<"N"<<endl;
}
}