zoukankan      html  css  js  c++  java
  • 尼姆博弈

    处理何种问题:有n堆物品,每堆物品数为 arr[i] ,双方轮流从中取物品,每次只能从一堆物品中取任意件物品,最少取一件,取到最后一件物品的人获胜,求谁最后获胜。

     

    性能:因为是有公式,所以时间复杂度为O(n)。

     

    原理:结论:把每堆物品数全部都异或起来,如果得到的值为0,那么先手必败,否则先手必胜。

    在这里补充一个知识点,异或:相同为0,不同为1,同一些数异或的顺序不会对最终结果有何影响。

    以三堆物品为例:

    我们用(a,b,c)表示某种局势,首先(0,0,0)显然是奇异局势,无论谁面对奇异局势,都必然失败。第二种奇异局势是(0,n,n),只要与对手拿走一样多的物品,最后都将导致(0,0,0)。仔细分析一下,(1,2,3)也是奇异局势,无论对手如何拿,接下来都可以变为(0,n,n)的情形。

    重点:任何奇异局势(a,b,c)都有a^b^c =0。

    如果我们面对的是一个非奇异局势(a,b,c),要如何变为奇异局势呢?假设 a < b< c,我们只要将 c 变为 a^b,即可,因为有如下的运算结果: a^b^(a^b)=(a^a)^(b^b)=0^0=0。要将c 变为a^b,只要从 c中减去 c-(a^b)即可。

     例1。(14,21,39),14^21=27,39-27=12,所以从39中拿走12个物体即可达到奇异局势(14,21,27)。

    例2。(55,81,121),55^81=102,121-102=19,所以从121中拿走19个物品就形成了奇异局势(55,81,102)。

    例3。(29,45,58),29^45=48,58-48=10,从58中拿走10个,变为(29,45,48)。

    备注:记住结论:异或结果为0,先手必败,否则必胜。

     

    输入样例解释

    5//n堆

    12 58 6 22 54//每堆石子个数

    输出样例解释

    First Win //先手胜

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    
    int main()
    {
        int n,temp,ans;
        while(~scanf("%d",&n))
        {
            ans=0;// 任意一个数异或 0 ,都是该数
            for(int i=0;i<n;++i)
            {
                scanf("%d",&temp);
                ans=(temp^ans);//异或运算符优先度较低,注意加括号
            }
            if(ans)
                printf("First Win
    ");
            else
                printf("First Lose
    ");
    
        }
        return 0;
    }
    

      

  • 相关阅读:
    java里如何使用输入流和输出流实现读取本地文件里内容和写出到本地文件里
    Windows 命令行基础(博主推荐)
    Python2.7编程基础(博主推荐)
    27 个Jupyter Notebook的小提示与技巧
    java里如何实现循环打印出字符或字符数组里的内容
    [转]angularjs之ui-grid 使用详解
    [转]AngularJS 实现 Table的一些操作(示例大于实际)
    [转]js 回车转成TAB(利用tabindex)
    [转] Entity Framework添加记录时获取自增ID值
    [转]使用依赖关系注入在 ASP.NET Core 中编写干净代码
  • 原文地址:https://www.cnblogs.com/l1l1/p/9488405.html
Copyright © 2011-2022 走看看