栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

博弈论(NIM游戏)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

博弈论(NIM游戏)

这个题目还是非常有意思的

首先 先手的状态有三种

先手必赢: 先手的下一个状态是必输状态(也就是说先手拿完以后的下一个状态是必输状态)
先手必败:1. 先手的下一个状态是必赢状态(这跟着上面的想也能想出来吧)
2. 没有后继状态的话也是先手必输(因为先手拿的时候就没有后继状态了,所以先手的时候一定是最后一个操作,且这个操作无法执行【因为是无后继状态】,所以必输)

我们可以使用异或运算来解决这个问题

  1. 没有后继状态就是 0 ^ 0 ^ 0 ^ 0 = 0这样的话开局就是0所以先手根本无法下手 —》 必输!!
  1. 先手的下一个状态是必输状态)) 我们假设 a 1 a_1 a1​ ^ a 2 a_2 a2​ ^ a 3 a_3 a3​ ^ … ^ a n a_n an​ = k ≠ not= ​= 0
    如果我们要将 a i a_i ai​改成 a i a_i ai​’ 就可以得到 a i a_i ai​ = a i a_i ai​’ ^ k. 然后我们根据异或的定义,一定存在奇数个 a i a_i ai​ 在k的二进制下的最高位为1.满足这个条件的 a i a_i ai​ 一定也满足 a i a_i ai​ > a i a_i ai​’ ^ k,因此也是合法移动

例如:下面的俩个式子一定可以得到 a ^ k < a;

a :110110 1 001010 
k :       1 101101

3.没有后继状态的是先手必输 —》 假设最终得到的 a 这个数 我们要将 a 改成 a’ 那么根据异或运算会得到 a = a'
故不成立,所以无法得到一个必输的状态,那么就代表他当前所处的这个状态是必输的。

于是就可以得到非常简单的代码
#include 

using namespace std;
int n;

int main()
{
    cin >> n;
    int res = 0;
    
    for (int i = 0; i < n; ++i)
    {
        int x;
        cin >> x;
        res ^= x;
    }
    if(res) cout << "Yes";
    else cout << "No";
    return 0;
    
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/873145.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号