博弈(三) 尼姆博弈(Nimm Game)

4 篇文章 0 订阅

##尼姆博弈(Nimm Game)##
有3堆任意多的物品(x, y, z)。两个人轮流拿,每次只能从一堆中拿,至少拿一个,至多不限。拿到最后者胜利。
结论:
必败点为 xyz = 0。(^为异或)
证明:
如果当前局势为(0,0,0)。先手肯定输。其中000=0
如果当前局势为(0,n,n)。先手肯定输。因为无论先手怎么拿,后手都可以从另一堆里拿相同多个。最终转化成(0,0,0)的情况。其中0nn=0
如果当前局势为(1,2,3)。先手肯定输。无论先手怎么拿,后手都可以将局势转为(0,n,n)的情况。其中123=0
以(1,2,3)为例:

10进制二进制
101
210
311

当前为奇异局势当且仅当二进制的各位的和为偶数,称达到平衡态,达到平衡态的每一位称位平衡位。无论先手怎么拿,后手都可以通过一步操作将局势转为新的平衡态。所以xyz=0为奇异局势。先手必输。
将非奇异局势转化为奇异局势只需将z变成xy即可。因为xy^z = xy(x^y) = (xx)(y^y) = 0^0 = 0
任意堆的推广:
1堆的时候先手赢。x != 0
2堆的时候取决于两堆的数目是否相等,相等的话xy=0,后手赢,不相等xy!=0,先手赢
推广到任意多堆的情况(x1, x2, x3··· ···xn)
例如当n=4的时候,各堆大小分别是8,12,14,16

十进制二进制
801000
1201100
1401110
1610000

先手可以从16的堆里拿走6个使之成为平衡态

十进制二进制
801000
1201100
1401110
1001010

之后无论后手怎么拿,先手都可以使之重新成为平衡态。所以最后先手一定胜利。
递推关系的验证:
1.每一个n状态(必胜态)都可以通过一步转为p状态(必败态)
例如当前异或和X为1000101,总可以寻找到一个堆Y与X最高位的同位为1,例如Y=1001110,Z = X^Y=0001011,Z肯定小于Y,则可以将Y堆拿出(Y-Z)个物品,使得异或和为0达到平衡态。
设没操作之前的异或和为X,当前堆为Y,其他堆异或和为Z,即ZY=X,然后将当前堆改为YX。则操作之后的异或和等于ZYX=X^X=0(p状态)
2.每个p状态不可能通过一步操作转为p状态
p状态异或和为0,如果只对一堆操作,无论拿多少个异或和都不可能为全0。
所以对于任意多堆时结论仍然成立。
例题:
HDU - 1850
代码:

#include<bits/stdc++.h>

using namespace std;
const int maxn = 100 + 5;
int a[maxn];
int n;

int main() {
    while(cin >> n, n) {
        int ans = 0;
        for(int i = 0; i < n; i++) {
            cin >> a[i];
            ans ^= a[i];
        }
        int cnt = 0;
        for(int i = 0; i < n; i++) {
            if(a[i] > (a[i]^ans)) cnt++;
        }
        cout << cnt << endl;
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Chook_lxk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值