zoukankan      html  css  js  c++  java
  • AcWing 891. Nim游戏

    题目传送门

    一、Nim游戏介绍

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

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

    据说,它源自中国,经由被贩卖到美洲的奴工们外传。辛苦的工人们,在工作闲暇之余,用石头玩游戏以排遣寂寞。后来流传到高级人士,则用便士(Pennies),在酒吧柜台上玩。

    最有名的玩法,是把十二枚便士放成(3、4、5)三列,拿光铜板的人赢。

    后来,大家发现,先取的人只要在(3)那列里取走(2)枚,变成了(1、4、5),就能稳操胜券了,游戏也就变得无趣了。

    于是大家就增加列数,增加铜板的数量,这样就让人们有了毫无规律的感觉,不易于把握。

    二、举个栗子

    • (2)(3)两堆石子,甲先来,从(3)那堆中取(1)个,留下两堆,分别是(2)(2)

    • 以后不管乙怎么拿,甲都和他在相反的一堆中做同样的操作,这样,肯定是乙最先面对(0)(0)状态。

    三、结论

    在两名选手都足够聪明,每一步都是最优解的情况下:
    (a_1) ^ (a_2) ^ ... ^(a_n=0) 先手必败
    (a_1) ^ (a_2) ^ ... ^(a_n eq0) 先手必胜
    就是把所有堆的石子个数异或起来,结果是零,先手必败,不是零,先手必胜。

    四、扩展问题

    如果(Nim)游戏中的规则稍微变动一下,每次最多只能取(K)个,怎么处理?

    方法是将每堆石子数(mod (k+1)).

    五、C++ 代码

    #include <bits/stdc++.h>
    
    using namespace std;
    const int N = 100010;
    
    int main() {
        //优化输入
        ios::sync_with_stdio(false);
        int n;
        cin >> n;
    
        int res = 0;    //起始值是0,因为任何数与0进行异或都它本身
        while (n--) {
            int x;
            cin >> x;
            res ^= x;
        }
        if (res) puts("Yes"); //异或值是非零,则可以先手通过某种办法将异或值变为零
        else puts("No");      //异或值是零,必败
        return 0;
    }
    
  • 相关阅读:
    libnids-1.24 使用源码问题
    Linux学习man page
    shell 脚本,提取文件中的内容
    shell中的语法(1)
    python 爬取百度翻译进行中英互译
    matlab等高线绘制
    matlab 对tif数据高程图的处理分析
    python网络爬虫与信息提取 学习笔记day3
    python网络爬虫与信息提取 学习笔记day2
    python网络爬虫与信息提取 学习笔记day1
  • 原文地址:https://www.cnblogs.com/littlehb/p/15391869.html
Copyright © 2011-2022 走看看