bzoj1022/洛谷P4279 关于Nim游戏的一点理解

题目分析

https://www.cnblogs.com/Robert-Yuan/p/5282669.html

Nim游戏

马上就要到高考假了,老师给大家发了许多许多卷子作为礼物,小L将各科卷子分类放好之后,小B说了一个提议:

我们来玩一个游戏吧,每次选择一堆卷子,轮流从其中拿走几张,但是不能不拿。谁没有卷子拿了,谁就输了。输了的人要帮赢了的人写一张卷子。

小L觉得海星,反正她也不想写卷子。结果小B赢了无数次,这令小L困惑不已,只见小B露出了一个神秘的微笑。
莫非是有必胜策略?小L仔细思考,发现自己果然被小B坑了:
假设第i堆试卷有 S(i) S ( i ) 张,则S的异或和k为0的为必败状态P,否则为必胜状态N。这是由于:

1.如果当前处于N,则下一步必到P
如果当前取了第i堆的石子,使该堆变为 B(i) B ( i ) 个石子, A(1)xorA(2)xor...B(i)xor...=k2=0 A ( 1 ) x o r A ( 2 ) x o r . . . B ( i ) x o r . . . = k 2 = 0 ,则有 k2xork=0 k 2 x o r k = 0 ,则有 A(i)xorB(i)=0 A ( i ) x o r B ( i ) = 0 A(i)=B(i) A ( i ) = B ( i ) ,与不能不取矛盾。
2.如果当前处于P,则下一步可到N
找到所有A中的最大值A(i),则其二进制下最高为1的位一定是k二进制下最高为1的位,那么A(i)异或k小于A(i),所以让A(i)异或一下k是一个合法策略,并且这样 k2 k 2 会变为0.

Nim游戏的变形

小B又露出一个神秘的微笑,然后说道:

这样吧,我们再玩一轮。谁拿走最后一张卷子就输了,如果你赢了就不用帮我写卷子了。

小L觉得自己已经学会了Nim游戏,一定不会输的!
……然后就输了。
难道这种游戏还有什么玄机?小L略一思索,忽然恍然大悟。
记老师很仁慈只布置了一张试卷的堆为 K1 K 1 ,有多于1张卷子的堆为 K2 K 2
然后记 P P 状态下,无K2堆的记做 P0 P 0 ,一个 K2 K 2 堆的记做 P1 P 1 ,否则记做 P2 P 2 。同理定义 N0 N 0 N1 N 1 N2 N 2
那么:
1. N0 N 0 必败。

因为有奇数个 K1 K 1 堆,轮流拿就先手必败了。

2. P0 P 0 必胜。

偶数个 K1 K 1 堆,轮流拿先手必胜。

3. N1 N 1 必胜。

因为如果有奇数个 K1 K 1 堆,就把那个 K2 K 2 堆一窝端了。否则让 K2 K 2 堆留下一张“革命的火种”

4. P1 P 1 不存在。

因为那些 K1 K 1 堆异或和不是1就是0,显然剩下那个 K2 K 2 堆里面试卷数量是多少都不可能让总异或和为0。

5. N2 N 2 必胜, P2 P 2 必败。

你不可能一口气让两个 K2 K 2 堆消失,所以 P2 P 2 只能转到 N1 N 1 或是 N2 N 2 ,当然 N1 N 1 是必胜的啦,所以要尽量往 N2 N 2 转。
N2 N 2 状态下,A最大的那一堆i一定是个 K2 K 2 堆,让其异或k。如果此时它变成了一个 K1 K 1 堆,说明除i堆外的异或和为1。显然其他堆要么全是 K1 K 1 堆(但那就不是 N2 N 2 状态了),要么有两个以上的 K2 K 2 堆,这样操作后的 K2 K 2 堆个数不会少于两个。而如果异或后它还是一个 K2 K 2 堆,那么 K2 K 2 堆个数也不会少于两个,也就是说 N2 N 2 状态绝对可以转化为 P2 P 2 状态。
所以这么转来转去,最后的归宿一定是 N1 N 1 状态了啊……
然后就 N2 N 2 必胜, P2 P 2 必败了。

技不如人,甘拜下风。小L只能帮小B去写卷子了。

代码

#include<bits/stdc++.h>
using namespace std;
int read() {
    int q=0;char ch=' ';
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') q=q*10+ch-'0',ch=getchar();
    return q;
}
#define RI register int
int T,n,js,kl;
int main()
{
    T=read();
    while(T--) {
        n=read();js=0,kl=0;
        for(RI i=1;i<=n;++i) {
            int x=read();kl^=x;
            if(x>1) ++js;
        }
        if((js==0&&kl==0)||(js>0&&kl)) puts("John");
        else puts("Brother");
    }
    return 0;
}

Nim游戏其他变形

n n 堆卷子,每次可以选择一堆,取1 m m 张,不能取的人输,求先后手谁胜。

将所有堆的卷子数都模上m+1,然后异或起来,为0则后手胜,否则先手胜。

n n 堆卷子,每次可以从k堆中拿卷子,至少拿走一张卷子,不能取的人输,求先后手谁胜

将所有堆卷子数转化为 k+1 k + 1 进制,然后做不进位的加法,为0则后手胜,否则先手胜。

有一个台阶,其中有几阶上放了几堆卷子,每次可以选择一堆,设该堆在第i阶,从其中取至少一张卷子,移到第i-1阶,0阶的卷子不能动,求先后手谁胜。

只看奇数阶上的卷子,异或起来为0则后手胜,否则先手胜。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值