题目描述
意思就是说两个人轮流剪纸片,直到有一个人剪出1*1的方格就算这个人赢了。然后给出纸片的长和宽,求先手会赢还是会输
(1<=n,m<=200)
题解
看了一眼,这不是裸的SG吗
啪啪啪写完,一交T了,居然没算复杂度就交了。。。
首先明确,把纸片分成两部分之后的SG是分成两个纸片的异或。
一个非常自然的想法就是,枚举如何分割这个纸片,然后求mex。
但是这样显然会T。(200^4)
其实作为一个正常人,1*x这样的纸片是不会切出来的,这显然是一个必败局面。
然后2*2,2*3,3*2这样的局面也是必败的,搜到这样的局面就可以退出了。
最后,比如一个5*5的纸片,切成3*5+2*5和切成2*5+3*5是一样的。
所以一个x*y的纸片枚举的时候从2枚举到x/2就行。
这样就能AC了
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=;
int sg[N][N],a[N*],n,m;
int get_sg(int x,int y){
if(sg[x][y]!=-)return sg[x][y];
bool a[];
memset(a,,sizeof(a));
for(int i=;i<=x-i;i++)a[get_sg(i,y)^get_sg(x-i,y)]=;
for(int i=;i<=y-i;i++)a[get_sg(x,i)^get_sg(x,y-i)]=;
for(int i=;;i++){
if(a[i]==)return sg[x][y]=i;
}
}
int main(){
memset(sg,-,sizeof(sg));
sg[][]=sg[][]=sg[][]=;
while(scanf("%d%d",&n,&m)!=EOF){
if(get_sg(n,m)==)printf("LOSE\n");
else printf("WIN\n");
}
return ;
}