博弈论入门之nim游戏
nim游戏
nim游戏
有两个顶尖聪明的人在玩游戏,游戏规则是这样的:
有n堆石子,两个人可以从任意一堆石子中拿任意多个石子(不能不拿),没法拿的人失败。问谁会胜利
nim游戏是巴什博奕的升级版(不懂巴什博奕的可以看这里)
它不再是简单的一个状态,因此分析起来也棘手许多
如果说巴什博奕仅仅博弈论的一个引子的话,
nim游戏就差不多算是真正的入门了
博弈分析
面对新的博弈问题,我们按照套路,从简单的情况入手
当只有一堆石子的时候,先手可以全部拿走。先手必胜
当有两堆石子且石子个数相同的时候,先手不论拿多少,后手都可以从另一堆中拿同样多的石子,先手必败,否则先手必胜
当有三堆的时候呢?
当有n堆的时候呢?
这样玩下去却是很繁琐,不过前辈们总结出了一条非常厉害的规律!
定理解析
定理
对于nim游戏,前辈们发现了一条重要的规律!
当(n)堆石子的数量异或和等于(0)时,先手必胜,否则先手必败
证明
设oplus表示异或运算
nim游戏的必败态我们是知道的,就是当前(n)堆石子的数量都为零
设a[i]表示第i堆石子的数量,那么当前局面就是
0 oplus 0 oplus 0 oplus dots oplus 0 = 0
- 对于先手来说,如果当前局面是
a_1 oplus a_2 oplus a_3 oplus dots oplus a_n = k
那么一定存在某个a_i,它的二进制表示在k最高位上一定是1
我们将a_i oplus k,这样就变成了
a_1 oplus a_2 oplus a_3 oplus dots oplus a_n oplus k = 0
此时先手必胜
- 对于先手来说,如果当前局面是
a_1 oplus a_2 oplus a_3 oplus dots oplus a_n = 0
那么我们不可能将某一个(a_i)异或一个数字后使得
a_1 oplus a_2 oplus a_3 oplus dots oplus a_n = 0
此时先手必败
代码
#include<cstdio>
using namespace std;
int a[10001];
int main()
{
int Test;
scanf("%d",&Test);
while(Test--)
{
int ans=0,N;
scanf("%d",&N);
for(int i=1;i<=N;i++) scanf("%d",&a[i]);
for(int i=1;i<=N;i++) ans=ans^a[i];
ans==0?printf("Non"):printf("Yesn");
}
return 0;
}
题目
临时还没有做太多题目,以后做多了慢慢补吧
- POJ 1704
估计没几个人能一眼秒吧233
题解
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法