POJ - 2975(Nim)博弈

题意:

给定一种Nim状态(相当于含N堆石头),求能有几种方法能通过调整某一堆石头的状态(只准取出),使新的Nim状态为必败态。(或者说求出所给的Nim游戏状态有多少种方法能够赢)

题解:

根据Nim游戏的证明过程:对于某个局面(a1,a2,...,an),若a1^a2^...^an不等于0,一定存在某个合法的移动,将ai改变成ai'后满足a1^a2^...^ai'^...^an=0。不妨设a1^a2^...^an=k,则一定存在某个ai,它的二进制表示在k的最高位上是1(否则k的最高位那个1是怎么得到的)。这时ai^k<ai一定成立。则我们可以将ai改变成ai'=ai^k,此时a1^a2^...^ai'^...^an=a1^a2^...^an^k=0。

 例:有4堆物品,数量分别为:7、11、13、4。

a1 = 0111
a2 = 1011
a3 = 1101
a4 = 0100

k=a1^a2^a3^a4=0101,根据上述结论,得出7、13、4是符合的。

7:a2^a3^a4=0010 < a1,那么可以通过从a1中取出0101来得到a1'=0010,使得a1'^a2^a3^a4=0。
11:a1^a3^a4=1110 > a2,此时无法从a2中取出部分物品,使得a1^a2'^a3^a4=0。
13:a2^a3^a4=1000 < a3,那么可以通过从a3中取出0101来得到a3'=1000,使得a1^a2^a3'^a4=0。
4:a2^a3^a4=0001 < a4,那么可以通过从a4中取出0011来得到a4'=0001,使得a1^a2^a3^a4'=0。

代码I:

#include <bits/stdc++.h>
#define clr(str,x) memset(str,x,sizeof(str))
#define FRER() freopen("in.txt","r",stdin);
#define FREW() freopen("out.txt","w",stdout);
#define MAX_INF 0x7fffffff
#define INF 0x3f3f3f3f
#define maxn 1005
using namespace std;
int n;
int k[maxn];

int main()
{

    while (scanf("%d", &n), n)
    {
        for (int i = 0; i < n; ++i)
        {
            scanf("%d", k + i);
        }

        int XOR = 0;
        for (int i = 0; i < n; ++i)
        {
            XOR ^= k[i];
        }

        int result = 0;
        for (int i = 0; i < n; ++i)
        {
            if (k[i] > (XOR ^ k[i]))
            {
                ++result;
            }
        }
        printf("%d\n", result);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值