Marbles(Sg函式,終態為必勝態)
阿新 • • 發佈:2018-12-18
題意:
有多個點(x,y)(x>0,y>0),雙方可以移動一個點到,第一個移到的玩家獲勝,多個點可以重複,穿越。
解析:
首先是Sg函式,這個沒有問題。但是這道題有點不同,雖然是必敗態,但是都是必勝態,顯然其他地方只能走到這三種必勝態。
將這些狀態看成終態(此狀態直接決定勝負),但是此時終態為勝態(平時終態為敗態)
我們需要消除這些勝態的影響:將Sg值變為inf
當然,我們最後算異或的時候,如果有一個為終態,直接輸出“Y”即可
#include<bits/stdc++.h>
using namespace std;
int read(){ int ans=0; char last=' ',ch=getchar();
while(ch<'0' || ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}
int sg[109] [109];
bool vis[200];
void init(){
memset(sg,0,sizeof(sg));
for(int i=0;i<=100;i++)sg[i][i]=sg[i][0]=sg[0][i]=199;
for(int i=0;i<=100;i++){
for(int j=0;j<=100;j++){
if(i==j||i==0||j==0)continue;
memset(vis,0,sizeof(vis));
for(int a=0;a<i;a++)vis[sg[a] [j]]=1;
for(int b=0;b<j;b++)vis[sg[i][b]]=1;
int ti=i-1,tj=j-1;
while(min(ti,tj)>=0){
vis[sg[ti][tj]]=1;
ti--,tj--;
}
for(int k=0;;k++){
if(!vis[k]){sg[i][j]=k;break;}
}
}
}
}
int main(){
init();
int n;scanf("%d",&n);
int Nim=0;
for(int i=1;i<=n;i++){
int a,b;
scanf("%d%d",&a,&b);
if(a==b)return 0*printf("Y\n");
Nim^=sg[a][b];
}
if(Nim!=0)printf("Y\n");
else printf("N\n");
}