题解:
这道题比较特殊,要求将棋子都移动到最后一堆。
所以我们的状态不是这一堆有多少棋子,而是这个棋子在第几堆。
然后对于棋子求一下$SG$函数。
此时$ans$本应等于所有棋子$SG$函数值的异或和,但是$a^a=0$,相当于偶数自己和自己约掉,
那么$ans^=sg[i](a[i]&1)$即可。
要保证先手必胜,只要保证第一步操作后的$ans$为$0$就好了。
所以$ans^sg[i]^sg[j]^sg[k]==0$时更新答案即可。
代码:
#include<cstdio> #include<cstring> int t,n,a[25],sg[25]; int dfs(int x) { if(~sg[x])return sg[x]; if(x==n)return sg[x]=0; bool tmp[205]={0}; for(int i=x+1;i<=n;i++) for(int j=i;j<=n;j++) tmp[dfs(i)^dfs(j)]=1; for(int i=0;;i++)if(!tmp[i])return sg[x]=i; } int main() { scanf("%d",&t); while(t--) { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); memset(sg,-1,sizeof(sg)); dfs(1); int ans = 0; for(int i=1;i<=n;i++)if(a[i]&1)ans^=sg[i]; if(!ans) { printf("-1 -1 -1\n0\n"); continue; }else { int x=-1,y,z,sum=0; for(int i=1;i<=n;i++)if(a[i]) for(int j=i+1;j<=n;j++) for(int k=j;k<=n;k++) if(!(ans^sg[i]^sg[j]^sg[k])) { if(x==-1)x=i,y=j,z=k; sum++; } printf("%d %d %d\n%d\n",x-1,y-1,z-1,sum); } } return 0; }
原文:https://www.cnblogs.com/LiGuanlin1124/p/10306678.html