• 尼姆博弈


    处理何种问题:有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;
    }
    

      

  • 相关阅读:
    Homework template (latex)
    Basic skill of searching
    国庆第三次集训: 2012 ACM-ICPC Asia Regional Contest Chengdu Site
    新学期随笔
    暑期集训感想
    暑期集训 DP 篇
    POJ 1195 Mobile Phones 二维树状数组
    51Nod1246 罐子和硬币,不能均分的题
    一维战舰,一道考区间的好题
    51NOD 1268 和为K的组合 搜索水题
  • 原文地址:https://www.cnblogs.com/l1l1/p/9488405.html
Copyright © 2020-2023  润新知