题目:https://www.luogu.org/problemnew/show/P2148
先打表找个规律:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int sg[25][25]; void dfs(int x,int y) { if(sg[x][y]!=-1)return; int sum=0; for(int i=1;i<x;i++) { dfs(i,x-i); sum|=(1<<sg[i][x-i]); } for(int i=1;i<y;i++) { dfs(i,y-i); sum|=(1<<sg[i][y-i]); } for(int i=0;i<=20;i++) if((sum&(1<<i))==0) { sg[x][y]=i;sg[y][x]=i; return; } } int main() { memset(sg,-1,sizeof sg); sg[1][1]=0; for(int i=1;i<=20;i++) { for(int j=1;j<=20;j++) { dfs(i,j); printf("%3d",sg[i][j]); } printf(" "); } return 0; }
根据数字出现的规律性,发现:
SG=1:i % 2 ==1 && j % 2 ==1;
SG=2:i % 4 == 1,2 && j % 4 == 1,2;
SG=3:i % 8 == 1,2,3,4 && j % 8 == 1,2,3,4;
……
所以按规律写好了。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; ll T,n,ans; ll sg(ll x,ll y) { ll tmp=2; for(ll i=0;;i++,tmp*=2) if((x-1)%tmp<(tmp>>1)&&(y-1)%tmp<(tmp>>1)) return i; } int main() { scanf("%d",&T); while(T--) { ans=0; scanf("%d",&n); for(ll i=1,x,y;i<=n/2;i++) { scanf("%d%d",&x,&y); ans^=sg(x,y); } if(ans)printf("YES "); else printf("NO "); } return 0; }