bzoj1022
蜜汁博弈,然而蒟蒻一枚,只会写二进制拆分的,于是T了。
在看完大佬的博客后好像有所领悟。。
情况1. 每堆石子数量都为1时,堆数为偶数时先手胜,此时Nim和为0
反之,堆数为奇数时先手必败
情况2. 至少有一堆石子数量大于1时,
1)若只有一堆石子数量大于1(此时Nim和!=0),先手可一定可以将局面变为奇数个1,使后手进入必败状态
2)若有>=2堆石子数量大于1:
初始的Nim和==0时:
*1 取石子相当于减小某个数,即把某个数的某个二进制位k由1变为0,再改变低于k的位数
*2 二进制位k为1的数有偶数
假设先手将某数a的最高第k位改为0,又改了k之后的某些位,那么后手完全可以也找到另一个二进制第k位为1的数b,
在第k位及之后做相同修改。若修改b之后,还存在大于1的数,就这样修改,并循环往复; 否则,后手完全可以不
修改b,而是转化为情况 2- 1) 的先手而取胜。此种情况后手必胜
初始的Nim和!=0时:先手可通过调整最大的数,将局面变为 Nim和==0,他就成为了上面情况的"后手"。此种情况先手必胜
---------转自cjk_cjk
#include <stdio.h> #include <algorithm> #include <cstring> #include <cmath> #include <queue> #include <vector> using namespace std; int t,n,a[60],flag; template <class T> void read(T & x) { x=0;char c=getchar();int f=0; while(c<'0'||c>'9'){f|=(c=='-');c=getchar();} while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^=48),c=getchar(); x=f?-x:x; } int main() { read(t); while(t--) { memset(a,0,sizeof(a));flag=0; read(n); for(int i=1;i<=n;i++)read(a[i]); int sum=0; for(int i=1;i<=n;i++) { sum^=a[i]; if(a[i]>1)flag=1; } if(!sum&&!flag)printf("John\n"); else if(sum&&flag)printf("John\n"); else printf("Brother\n"); } return 0; }
交的时候m莫名re了~??