Nim游戏(博弈论)

今天我想跟大家分享的是一个博弈论游戏,我觉得这种类型的题目第一次遇到还是很有思维含量的,里面着重介绍了一些难懂的点,不说废话了,直接引入正题啦

 

 

Nim游戏

给定 n 堆石子,两位玩家轮流操作,每次操作可以从任意一堆石子中拿走任意数量的石子(可以拿完,但不能不拿),最后无法进行操作的人视为失败。

问如果两人都采用最优策略,先手是否必胜。

输入格式

第一行包含整数 n

第二行包含 n 个数字,其中第 ii 个数字表示第 ii 堆石子的数量。

输出格式

如果先手方必胜,则输出 Yes

否则,输出 No

数据范围

1n10^5,
110^9

输入样例:

2
2 3

输出样例:

Yes


先说下结论吧,然后我会给出证明
当这n个数的异或结果为0时,先手必败,否则先手必胜(前提是他们都足够聪明哈哈)
证明:
不难发现,当最后一个玩家拿走最后的石子后,所有的石子都被拿完了,那么此时所有石子的异或值肯定为0;
我们假设初始值满足所有石子的异或和不为0,我们证明先手能够做到将所有石子的异或值变为0:
假设a1^a2^……^an=x!=0
我们假设x的二进制位串上1所在的最高位为k,那么x1~xn中至少有一个数第k位也为1,不妨假设这堆石子个数为aj,
先来证明一下aj^x<aj
不难发现,aj中第k位由1变成了0,而第k位之上的数都没有发生改变,故
aj^x<aj显然成立
那我们就将aj这堆石子数目取至aj^x;则a1^a2^……^aj^x^……^an=x^x=0;
所以结论成立
下面我们证明一下当原先石子异或值为0,我们怎样操作都无法保证异或值仍然为0
假设
a1^a2^……^an=0,我们将aj取至m(aj>m)仍然有
a1^a2^……^m^……^an=0成立,我们将两个式子异或在一起可得
aj^m=0,又因为aj!=x,所以这是不可能的,故原假设不成立,证毕!
通过这两个结论的证明,我们可以发现一个玩家可以将石子异或值由非0变为0,所以只要一个玩家一直能保证石子异或值为0,那么他就会必胜!
代码比较简单,重点是要理清思路
#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    cin>>n;
    int ans=0,t;
    while(n--)
    {
        cin>>t;
        ans^=t;
    }
    if(ans) printf("Yes");
    else printf("No");
    return 0;
}

希望大家能够喜欢!

posted @ 2021-05-06 20:59  AC--Dream  阅读(217)  评论(0编辑  收藏  举报