取火柴 c语言程序,取火柴游戏||Nim博弈

本文探讨了两种博弈策略,首先是圆形桌子上放盘子的博弈,证明了先手必胜的策略。接着分析了弱化版的 Nim 游戏,当两堆火柴数量相等时,先手必输。最后引入了经典的 Nim 游戏,通过异或运算揭示了先手优势的判断条件。当所有堆火柴异或和为0时,先手必败,否则必胜。文章通过代码展示了如何找到先手的获胜策略。
摘要由CSDN通过智能技术生成

好久之前看的sg函数了

好像就记住一个nim博弈qwq

第一次啊看的时候很迷,现在感觉可以了qwq

首先我们来看一个其他的游戏。(以下游戏只有两个人参与,且足够聪明)

两个人在一张圆形的桌子上放等大的盘子,最后一个无法放盘子的人输掉比赛

很显然,先手必胜。

为什么? 第一个人可以将盘子放在桌子的中心。

然后只要第二个人可以放置盘子,我们就在其中心对称的位置上放盘子。

如此,只要后手可以放,我先手就一定能放

可以看出,有时候如果处于先手必胜的状态时,模仿对手的策略不妨是个好方法。这可以保证如果游戏可以进行下去的话,先手就一定能进行下去。

我们再来看一个更nim游戏的弱化版

有两个火柴堆,每堆的火柴数不一定相同,每次一个人只能从一堆中选取若干个火柴并取走。没有火柴可取的人输

好像这和上个题没有什么关系qwq

我们假设两个火柴堆的数目都相同。那么肯定是先手必输

为什么?因为后手总可以从另一堆中取的和先手上一次取得一样的火柴。

只要先手可以取,后手就可以取。

所有该游戏的判定条件是,若两堆相等,先手必输,否则,先手必胜,先手总可以将两堆取成一样多

先手必胜时总有一种策略可以转移到后手必败

后手必败总是会转移到先手必胜

好像大佬如此说过

然后我们看van♂整版nim

先说结论,若所有火柴堆异或起来的值为0的话,先手必败,否则先手必胜

啥?mengbi qwq

(?`⊿′)?为什么和异或结合起来的啊喂

这是得益于毒瘤的二进制和更毒瘤的异或

异或有一个特殊的规律,就是一堆数异或时,若在同一个二进制位上1的个数是偶数,那么这一位异或起来以后是0,否则为1

二进制的话就是可以使用0/1表示所有数字

我们来看上一个游戏,我们将这两堆的剩余的火柴数转变成二进制。

发现我们先手取走一个数,就是改变其二进制为上的1的个数(只考虑奇偶性),而后手再去取的话就是将其奇偶性再变回来

然后我们再回去看为什么异或和是0时先手必输,因为先手拿走了某些火柴时,我们可以根据其拿走火柴的二进制表示,在其他一堆中拿走一些一些数字,使得其异或和重新为0;

怎么搞呢? 我们可以拿走一些数,也就是减某一个数,使得先手拿完后,(啰嗦警告)

所有堆中的每个二进制上的一的个数的和,我们总可以通过加减一个数,达到在某一个二进制位的1的个数进行加一or减一的效果

使得某一位二进制上的1的个数变为偶数。

从而使得游戏又恢复到了一开始的局面

end......

sg函数好像也是这个思想qwq

此题代码

#include

#include

#include

#include

using std::sort;

const int maxn=501000;

int data[maxn];

int main()

{

int n;

scanf("%d",&n);

int x=0;

for(int i=1;i<=n;i++)

{

scanf("%d",&data[i]);

x^=data[i];

}

if(x==0)

{

printf("lose");

return 0;

}

for(int i=1;i<=n;i++)

if((data[i]^x)<=data[i])

{

printf("%d %d\n",data[i]-(data[i]^x),i);

data[i]^=x;

break;

}

for(int i=1;i<=n;i++)

printf("%d ",data[i]);

}

原文:https://www.cnblogs.com/Lance1ot/p/9409384.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值