• 尼姆博奕


    有三堆物品,两人轮流从某一堆任取若干(大于0),最后取光者获胜。

    我们用(a,b,c)表示三堆的状态,其有三种奇异局势:

    1. (0,0,0)时,即无论谁面对(0,0,0),其必输。
    2. (0,n,n)时,自己在某一堆拿走k(k ≤ n)个物品,不论k为多少,对方只要在另一堆拿走k个物品,最后自己都将面临(0,0,0)的局势,必败。
    3. (1,2,3)时,也是必败,无论自己如何拿,接下来对手都可以把局势变为(0,n,n)的情形。

    这种奇异局势有特点,它们可以和二进制联系在一起:

      将这三堆物品的个数按照其二进制进行按位异或(⊕):(以1,2,3为例)

      1 =01
      2 =10
      3 =11 
      —————
      0 =00 

      对于任意的奇异局势,其结果都是0。

    那么对于一个非奇异局势,如何变成奇异局势?

    假设a<b<c,只需将c=a⊕b。因为a⊕b⊕(a⊕b)=(a⊕b)⊕(a⊕b)=0,即只需要将c进行c-(a⊕b)即可。

    推广:

    有n堆若干个物品,两个人轮流从某一堆取任意多的物品,规定每次至少取一个,多者不限,最后取光者得胜。

    假设有k堆,每堆的个数为:N1,N2,……,Nk。

    其二进制为:

      N1=an…a2a1

      N2=bn…b2b1

      ……

      Nk=kn…k2k1

    定义:尼姆博弈是平衡的当且仅当:

      an⊕bn⊕…⊕kn=0 

      ……

      a1⊕b1⊕…⊕k1=0

    Bouton定理:先手能够在非平衡尼姆博弈中取胜,而后手能够在平衡的尼姆博弈中取胜。

    根据是否是平衡尼姆博弈判断先手胜还是后手胜利

    C代码:

    #include <cstdio>
    using namespace std;
    int main(){
        int m,ans,n;
        while(~scanf("%d",&m)){
            n=ans=0;
            while(m--)
                scanf("%d",&n),ans^=n,printf("ans=%d
    ",ans);
            if(ans)printf("First
    ");
            else printf("Second
    ");
        }
    }

    例题

    桌子上有M堆扑克牌;每堆牌的数量分别为Ni(i=1…M);两人轮流进行;每走一步可以任意选择一堆并取走其中的任意张牌;桌子上的扑克全部取光,则游戏结束;最后一次取牌的人为胜者。

    Input
    输入数据包含多个测试用例,每个测试用例占2行,首先一行包含一个整数M(1<M<=100),表示扑克牌的堆数,紧接着一行包含M个整数Ni(1<=Ni<=1000000,i=1…M),分别表示M堆扑克的数量。M为0则表示输入数据的结束。
     
    Output
    如果先手的人能赢,请输出他第一步可行的方案数,否则请输出0,每个实例的输出占一行。
     
    Sample Input
    3
    5 7 9
    0
    Sample Output
    1
    #include<stdio.h>
    int main()
    {
        int x,m,a[110],i,ans;
        while(scanf("%d",&m),m)
        {
             x=ans=0;
             for(i=0;i<m;i++)
             {
                    scanf("%d",&a[i]);
                    x^=a[i];
             }
             for(i=0;i<m;i++)
             ans+=(a[i]>(x^a[i]));//a,b,c  ---因为a⊕b=a⊕b⊕c⊕c=x⊕c, 所以将所有的堆数进行异或得出x,然后再看哪一堆的个数比除其之外所有堆数的异或结果x^a[i]大,即为一种方案。
             printf("%d
    ",ans);
        }
        return 0;
    }
     
  • 相关阅读:
    (七)执行上下文和词法作用域&动态作用域案例分析
    (六)js的arguments
    (五)关于解构赋值
    (四)JavaScript深入之词法作用域和动态作用域
    jmeter获取token并请求失败Internal authentication failed 400
    jmeter造当前时间,未来时间,历史时间
    jmater分布式压力测试总结
    敏捷测试-基本流程
    致我测试之路的“七年之痒”
    jmeter解决登录token获取
  • 原文地址:https://www.cnblogs.com/LMIx/p/10700274.html
Copyright © 2020-2023  润新知