P2575 高手过招
直接搞好像搞不了
考虑转换模型
显然每一行棋子不会跑到其他行..
所以可以把每一行的情况看成一个子博弈
显然整个答案就是每一行的SG值的异或和
不懂的回去学SG函数...
考虑怎么分析一行的状况
可以发现空位的个数是不会变的
如果把每一段连续的棋子看成一块
整块的的值为块中棋子的个数
那么每次操作会使一块的值减少一个数 $a$
然后让右边的另一块增加 $a$
显然变成了阶梯Nim..
然后就可以搞了
(关于阶梯Nim,我是在 这里 学的,讲得很清楚)
代码很简单,不用注释了吧
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; int n,t,m,ans,b[27],k; bool flag; int main() { int a; scanf("%d",&t); while(t--) { ans=0; scanf("%d",&n); for(int i=1;i<=n;i++) { memset(b,0,sizeof(b)); scanf("%d",&m); for(int j=1;j<=m;j++) { scanf("%d",&a); b[a]=1; } int tot=0,j=20,fg=0; while(b[j]) j--; while(j--) { if(!b[j]) ans^= (fg?tot:0),fg^=1,tot=0; else ++tot; } ans^= (fg?tot:0); } if(ans) printf("YES\n"); else printf("NO\n"); } return 0; }