【博弈论】Nim游戏
Definition
这样的游戏被称为Nim游戏:
1、有两个玩家,轮流进行操作
2、是公平游戏。即面对同一局面两个玩家所能进行的操作是相同的。例如中国象棋不是公平游戏。因为面对同一个局面,红方只能移动红色棋子而不能移动黑方棋子,黑房同理。
3、一个玩家是输掉当且仅当他无法进行操作。例如如果是两个人轮流取石子的游戏,那么一个玩家输掉当且仅当他面前没有石子了。因为他下面无法进行取石子的操作。
一般的,Nim游戏指两个玩家轮流在好几堆东西中取物品,不能夸堆取,无法操作判负。
Solution
对于Nim游戏的解法,因为状态显然是不可逆的,所以可以对状态的转移图进行拓扑排序然后DP求解。但是对于大部分博弈题目,状态多的难以计算,所以需要考虑更简单的方法。
结论:一个Nim游戏中的状态是必败状态当且仅当每个子游戏的异或和为0.
这里子游戏代表构成Nim游戏中最基础的游戏。例如两个人轮流取三堆石子的游戏是三个取一堆石子的游戏组合而成的。对于每个子游戏显然可以用一个正整数代表当前的状态,即还剩多少石子。Nim游戏的子游戏状态异或和为\(0\),则必败。
证明:我有一个绝妙的想法,可惜这里写不开
对于一个异或和不为\(0\)的状态,那么他是必胜态。
考虑在一个必胜态下如何进行下一步。
设异或和是\(X\)。设\(X\)二进制的最高为1位是第\(k\)位。
那么显然存在至少一个状态使得他们二进制第\(k\)位为1。否则第k位异或和应该是0。
那么就任选一个第k位是1的状态,设他的状态是\(Y\),那么将他可以将\(Y\)这一堆取成\(Z=X~xor~Y\)那么得到的状态是必败状态。
证明如下:
首先,\(Y\)可以取成\(Z\)当且仅当\(Z~\leq~Y\)。首先证明\(Z~\leq~Y\)。
因为\(Y\)和\(X\)第\(k\)位都是\(1\),更高位都是\(0\)。那么异或后\(Z\)第\(k\)位一定是\(0\),更高位显然是\(0\)。所以\(Z\)的位数比\(Y\)的位数要少。那么显然\(Z~\leq~Y\)。
下面证明更改后的状态是必败状态
根据\(Z=X~xor~Y\),并且\(A~xor~A=~0~\)。可得:
更改后的状态
\(S~=~X~xor~Y~xor~Z~=~X~xor~Y~xor~(~X~xor~Y~)\)
\(=~(~X~xor~Y~)~xor~(~X~xor~Y~)~=~0~\)
一定是一个必败状态。
Example
Description
输入k及k个整数n1,n2,…,nk,表示有k堆火柴棒,第i堆火柴棒的根数为ni;接着便是你和计算机取火柴棒的对弈游戏。取的规则如下:每次可以从一堆中取走若干根火柴,也可以一堆全部取走,但不允许跨堆取,也不允许不取。
Input
第一行,一个正整数k
第二行,k个整数n1,n2,…,nk
Output
如果是先取必胜,请在第一行输出两个整数a,b,表示第一次从第b堆取出a个。第二行为第一次取火柴后的状态。如果有多种答案,则输出<b,a>字典序最小的答案(即b最小的前提下a最小)。
如果是先取必败,则输出“lose”。
Sample Input_1
3
3 6 9
Sample Output_1
4 3
3 6 5
Sample Input_2
4
15 22 19 10
Sample Output_2
lose
Hint
\(k~\leq~500000\)
\(n_i~\leq~1e9\)
Solution
板子题要啥solution
Code
#define rg register
#define ci const int
#define cl const long long int
typedef long long int ll;
namespace IO {
char buf[90];
}
template<typename T>
inline void qr(T &x) {
char ch=getchar(),lst=' ';
while(ch>'9'||ch<'0') lst=ch,ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
if(lst=='-') x=-x;
}
template<typename T>
inline void write(T x,const char aft,const bool pt) {
if(x<0) x=-x,putchar('-');
int top=0;
do {
IO::buf[++top]=x%10+'0';
x/=10;
} while(x);
while(top) putchar(IO::buf[top--]);
if(pt) putchar(aft);
}
template<typename T>
inline T mmax(const T a,const T b) {if(a>b) return a;return b;}
template<typename T>
inline T mmin(const T a,const T b) {if(a<b) return a;return b;}
template<typename T>
inline T mabs(const T a) {if(a<0) return -a;return a;}
template<typename T>
inline void mswap(T &a,T &b) {
T temp=a;a=b;b=temp;
}
const int maxn = 500010;
int n,ans;
int MU[maxn];
int main() {
qr(n);
for(rg int i=1;i<=n;++i) {
qr(MU[i]);ans^=MU[i];
}
if(!ans) {
puts("lose");return 0;
}
int _temp=1<<30;
while(!( _temp & ans )) _temp>>=1;
for(rg int i=1;i<=n;++i) if(MU[i] & _temp){
int z=ans^MU[i];
write(MU[i]-z,' ',true);write(i,'\n',true);
for(rg int j=1;j<=n;++j) {
if(j != i) write(MU[j],' ',true);
else write(z,' ',true);
}
break;
}
return 0;
}
Summary
Nim游戏是必败态当且仅当子游戏状态异或和为0。否则是必胜态。通过必胜态一定可以通过一步操作变成必败状态。
【博弈论】Nim游戏的更多相关文章
- 博弈论之Nim游戏
Nim游戏是组合游戏(Combinatorial Games)的一种,属于“Impartial Combinatorial Games”(以下简称ICG). 通常的Nim游戏的定义是这样的:有若干堆石 ...
- 博弈论入门之nim游戏
更好的阅读体验点这里 nim游戏 nim游戏 有两个顶尖聪明的人在玩游戏,游戏规则是这样的: 有\(n\)堆石子,两个人可以从任意一堆石子中拿任意多个石子(不能不拿),没法拿的人失败.问谁会胜利 ni ...
- 【博弈论】浅谈泛Nim游戏
Nim游戏在ACM中碰到了,就拎出来写写. 一般Nim游戏:有n堆石子,每堆石子有$a_i$个,每次可以取每堆石子中$[0,a_i-1]$,问先手是否有必胜策略. 泛Nim游戏:每堆石子有$a_i$个 ...
- [您有新的未分配科技点]博弈论入门:被博弈论支配的恐惧(Nim游戏,SG函数)
今天初步学习了一下博弈论……感觉真的是好精妙啊……希望这篇博客可以帮助到和我一样刚学习博弈论的同学们. 博弈论,又被称为对策论,被用于考虑游戏中个体的预测行为和实际行为,并研究他们的应用策略.(其实这 ...
- Nim游戏与SG函数 ——博弈论小结
写这篇博客之前,花了许久时间来搞这个SG函数,倒是各路大神的论文看的多,却到底没几个看懂的.还好网上一些大牛博客还是性价比相当高的,多少理解了些,也自己通过做一些题加深了下了解. 既然是博弈,经典的N ...
- BZOJ_3105_[cqoi2013]新Nim游戏_线性基+博弈论
BZOJ_3105_[cqoi2013]新Nim游戏_线性基+博弈论 Description 传统的Nim游戏是这样的:有一些火柴堆,每堆都有若干根火柴(不同堆的火柴数量可以不同).两个游戏者轮流操作 ...
- (博弈论)51NOD 1069 Nim游戏
有N堆石子.A B两个人轮流拿,A先拿.每次只能从一堆中取若干个,可将一堆全取走,但不可不取,拿到最后1颗石子的人获胜.假设A B都非常聪明,拿石子的过程中不会出现失误.给出N及每堆石子的数量,问最后 ...
- 洛谷$P$4301 $[CQOI2013]$新$Nim$游戏 线性基+博弈论
正解:线性基 解题报告: 传送门! 这题其实就是个博弈论+线性基,,,而且博弈论还是最最基础的那个结论,然后线性基也是最最基础的那个板子$QwQ$ 首先做这题的话需要一点点儿博弈论的小技能,,,这题的 ...
- 博弈论入门——Nim游戏引入
说实话,我真的对这个游戏看得是一脸懵逼,因为(我太弱了)我没有明白一些变量的意思,所以一直很懵,现在才明白,这让我明白博弈论(还可以骗钱)博大精深; 以下是我自己思考的过程,也许不严谨,但是最终明白了 ...
- 博弈论(nim游戏,SG函数)
说到自己,就是个笑话.思考问题从不清晰,sg函数的问题证明方法就在眼前可却要弃掉.不过自己理解的也并不透彻,做题也不太行.耳边时不时会想起alf的:"行不行!" 基本的小概念 这里 ...
随机推荐
- selenium,unittest——驾照科目一网上答题自动化
需求很简单,所有题目全选A,然后点提交出分,校验是否到达出分这步 遇到的坑有这几个,一个是assertIn哪个是校验哪个是文本要分清,还有code的编码统一到Unicode,最后就是xpath定位各个 ...
- EditorGUI控件输入监听
EditorGUI控件输入监听 在做编辑器开放的过程中,有时候要对用户输入进行判断和限制,但EditorGUI控件却没有触发回调,而是提供了一种麻烦的办法--使用EditorGUI.BeginChan ...
- Redis命令续
Redis 集合命令 下表列出了 Redis 集合基本命令: 序号 命令及描述 1 SADD key member1 [member2] 向集合添加一个或多个成员 2 SCARD key 获取集合的 ...
- 孤荷凌寒自学python第八十二天学习爬取图片2
孤荷凌寒自学python第八十二天学习爬取图片2 (完整学习过程屏幕记录视频地址在文末) 今天在昨天基本尝试成功的基础上,继续完善了文字和图片的同时爬取并存放在word文档中. 一.我准备爬取一个有文 ...
- Hyperledger fablic 1.0 在centos7环境下的安装与部署和动态增加节点
Hyperledger fablic 1.0 在centos7环境下的安装与部署和动态增加节点 一.安装docker 执行代码如下: curl -sSL https://get.daocloud.io ...
- df -h 卡住
mount 检查是否有挂载nfs的分区 网络挂载 如果有请umount -l /相应目录 umount -l 10.74.82.205:/letv/fet/nfs ...
- 条款02:尽量以const,enum,inline替换#define
一.概述 尽量少用预处理器——宏替换 二.细节 1. 关于宏替换之常量 旧版本:#define N 10; 新版本:const int n = 10; 比较:#define不被视为语言的一部分,记号名 ...
- 对alpha发布的总结技术随笔
对于今天的alpha发布,首先需要自我检讨,因为我们组没有展示作品.主要的原因还是我们投入的时间不足.我们的项目是约跑App,首先选择做安卓平台的东西,我们大家都需要熟悉新的开发软件Android S ...
- android异常Unable to instantiate activity ComponentInfo解决方法
我是下面提到的第四条: 在Order and Export 中 把新加的 android-support-v4.jar的前面的对号打上勾 保存:就可以了: 做android开发的可能都碰到" ...
- 文件传输底层是二进制 所以在传输前可以通过 InputStreamer 指定传输出的编码格式
文件传输底层是二进制 所以在传输前可以通过 InputStreamer 指定传输出的编码格式