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;
}
View Code

交的时候m莫名re了~??

posted @ 2017-10-25 21:43  新手-周  阅读(150)  评论(0编辑  收藏  举报