Both of players are using optimal game strategy. John starts first always. You will be given information about M&Ms and your task is to determine a winner of such a beautiful game.
Constraints:
1 <= T <= 474,
1 <= N <= 47,
1 <= Ai <= 4747
2 3 3 5 1 1 1
John Brother
/*巴什博弈:
如果是一堆取棋子的问题,每个人轮流取棋子 ,Q棋子总数为n,最多可取m个,至少取1个,最后取完者胜,我们可以判断若n%(m+1)==0,
则先手负,因为只要后手保证每次拿的个数与对手拿的个数和为m+1,就一定能剩下棋子给自己。若n%(m+1)!=0,则先手胜。
相反若最后取完者败,n%(m+1)==0,则先手胜,先手先取若干个,以后对手每次取的时候都保证拿得个数与对手拿的个数和为m+1,
后面就可用剩一个让对方取
尼姆博弈:
以上就是道例题,有不同堆,胜负与游戏规则无关(即谁最后取剩,或最后取败),因为只要将个堆的个数求异或,若不为零则先手就
可以控制自己想要的局面(特例,每堆都是1,若取完则负则要考虑堆数是否为奇数)
解题:
郁闷,最近老是碰见WA,冤神~~~开始先把result赋为1,再与每个输入的数异或,后来想想只能二进制是各位数与1异或才等于本身
第二次WA就是flag的值每判断好,人家d还没值呢就开始判断d了*/
#include<stdio.h>
int main()
{
register int i,j;
int t,n,result,d,flag;
scanf("%d",&t);
for(i=0;i<t;i++)
{
flag=0;
scanf("%d",&n);
scanf("%d",&result);
if(result>1) flag=1;
for(j=1;j<n;j++)
{
scanf("%d",&d);
if(d>1) flag=1;
result=result^d;
}
if(result!=0&&flag==1||flag==0&&n%2==0) printf("John/n");
else printf("Brother/n");
}
return 0;
}
例2http://acm.pku.edu.cn/JudgeOnline/problem?id=1704
/*我们把棋子按位置升序排列后,从后往前把他们两两绑定成一对。如果总个数是奇数,就把最前面一个和边界(位置为0)绑定。
在同一对棋子中,如果对手移动前一个,你总能对后一个移动相同的步数,所以一对棋子的前一个和前一对棋子的后一个之间有多少个空位置对最终的结果是没有影响的。
于是我们只需要考虑同一对的两个棋子之间有多少空位。
这样一来,题目就转换成了就成了POJ 1067 取石子问题,直接对每一段空位置的长度求异或就可以了。*/
#include<stdio.h>
#include<stdlib.h>
int comp(const void *a,const void *b){
return *(int *)a-*(int *)b;
}
int main()
{
register int i;
int a[1000];
int t,n,ret;freopen("E://in.txt","r",stdin);
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
if(n%2) {a[0]=0;i=1;n++;}
else i=0;
for(;i<n;i++)
scanf("%d",&a[i]);
qsort(a,n,sizeof(a[0]),comp);
ret=a[1]-a[0]-1;
for(i=2;i<n-1;i=i+2)
ret=ret^(a[i+1]-a[i]-1);
if(ret) printf("Georgia will win/n");
else printf("Bob will win/n");
}
return 0;
}