51 博弈方案数;

P - Being a Good Boy in Spring Festival

一年在外 父母时刻牵挂
春节回家 你能做几天好孩子吗
寒假里尝试做做下面的事情吧

陪妈妈逛一次菜场
悄悄给爸爸买个小礼物
主动地 强烈地 要求洗一次碗
某一天早起 给爸妈用心地做回早餐

如果愿意 你还可以和爸妈说
咱们玩个小游戏吧 ACM课上学的呢~

下面是一个二人小游戏:桌子上有M堆扑克牌;每堆牌的数量分别为Ni(i=1…M);两人轮流进行;每走一步可以任意选择一堆并取走其中的任意张牌;桌子上的扑克全部取光,则游戏结束;最后一次取牌的人为胜者。
现在我们不想研究到底先手为胜还是为负,我只想问大家:
——“先手的人如果想赢,第一步有几种选择呢?”

Input

输入数据包含多个测试用例,每个测试用例占2行,首先一行包含一个整数M(1<M<=100),表示扑克牌的堆数,紧接着一行包含M个整数Ni(1<=Ni<=1000000,i=1…M),分别表示M堆扑克的数量。M为0则表示输入数据的结束。

Output

如果先手的人能赢,请输出他第一步可行的方案数,否则请输出0,每个实例的输出占一行。

Sample Input

3
5 7 9
0

Sample Output

1

题目的意思是尼姆博弈先手有多少种必胜的方案,如果没有的输出0,如果有的话就输出方案数;

如果我们将当前的石子数量异或完后等于0的话就是必输了,否则的话就是必赢了,为什么会赢前面已经讲了,,,

所以如果我们想要赢得话我们就把当前的局势转换为平衡状态那么这样的话,对手就一定输了,那么我们可以利用一堆石子将当前的状态转换成平衡的条件是当前石子的数量可以产生等于其它堆石子sg值的异或值的sg值,这样的话操作后的石子sg值异或才是零,在这一道题目中转化一下题意就是,当前石子堆的数量如果是大于其它石子堆sg的异或值的话我们就一定有一个方案,我们可以拿一些石子让剩余的石子数目的sg值等于其它所有石子堆sg的异或值;

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

const int Max = 1e5+10;
int pre[Max],h[Max];
int a[Max];

int main(){
   int n;
   while(scanf("%d",&n)&&n){
   for(int i=1;i<=n;i++)  {
        scanf("%d",&a[i]);
        pre[i]=h[i]=0;
   }
   h[n+1]=0;
   h[0]=0;
   pre[0]=0;
   pre[n+1]=0;
   for(int i=1;i<=n;i++)  pre[i]=pre[i-1]^a[i];
   for(int i=n;i>=1;i--)  h[i]=h[i+1]^a[i];
   int num=0;
   for(int i=1;i<=n;i++) {
    if(a[i]>(pre[i-1]^h[i+1])){
        num++;
    }
   }
   printf("%d\n",num);
   }
   return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值