博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HNOI2007 分裂游戏
阅读量:5297 次
发布时间:2019-06-14

本文共 1342 字,大约阅读时间需要 4 分钟。

题解:

这道题比较特殊,要求将棋子都移动到最后一堆。

所以我们的状态不是这一堆有多少棋子,而是这个棋子在第几堆。

然后对于棋子求一下$SG$函数。

此时$ans$本应等于所有棋子$SG$函数值的异或和,但是a^a=0,相当于偶数自己和自己约掉,

那么ans^=sg[i](a[i]&1)即可。

要保证先手必胜,只要保证第一步操作后的$ans$为$0$就好了。

所以ans^sg[i]^sg[j]^sg[k]==0时更新答案即可。

代码:

#include
#include
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

你可能感兴趣的文章
java-swingButton
查看>>
[每天解决一问题系列 - 0002] Xcopy cannot copy file with long directory
查看>>
winform listview控件
查看>>
Android——requestWindowFeature
查看>>
iOS UDP 简易交互
查看>>
4-10 二分查找
查看>>
后台网页编辑器(带图片上传)
查看>>
部署---阿里云服务器,linux, ubuntu ,部署django用到的一些命令
查看>>
Linux awk
查看>>
mysql触发器
查看>>
sharing-jdbc实现读写分离及分库分表
查看>>
多指标综合评价方法汇总
查看>>
ASP.NET MVC的核心-Controller(控制器)
查看>>
SDWebImage缓存图片的机制(转)
查看>>
Interpolation methods
查看>>
【Xamarin挖墙脚系列:对设备/模拟器的查看调试监听】
查看>>
Building Web Apps with SignalR, Part 1
查看>>
python 小兵 三元运算符
查看>>
OpenGL ES着色器语言之变量和数据类型(二)(官方文档第四章)
查看>>
mongoTemplate更新一个Document里面的数组的一个记录。
查看>>