zoukankan      html  css  js  c++  java
  • HDU 2176 取(m堆)石子游戏 —— (Nim博弈)

      如果yes的话要输出所有情况,一开始觉得挺难,想了一下也没什么。

      每堆的个数^一下,答案不是0就是先取者必胜,那么对必胜态显然至少存在一种可能性使得当前局势变成必败的。只要任意选取一堆,把这堆的数目变成其他堆异或和即可,这样,它们异或一下就是0了(变成了必败态)。所以说,在这题就是,对任意一堆,变化以后的数目如果不大于这堆原来的数目,就是可能的第一次取的情况。代码如下:

     1 #include <stdio.h>
     2 #include <algorithm>
     3 using namespace std;
     4 const int N = 200000 + 5;
     5 int a[N];
     6 int main()
     7 {
     8     int n;
     9     while(scanf("%d",&n)==1 && n)
    10     {
    11         int temp = 0;
    12         for(int i=1;i<=n;i++) {scanf("%d",a+i);temp^=a[i];}
    13         if(temp == 0 )
    14         {
    15             puts("No");
    16             continue;
    17         }
    18         else
    19         {
    20             puts("Yes");
    21             for(int i=1;i<=n;i++)
    22             {
    23                 int other = a[i]^temp;
    24                 int x = other^0;
    25                 if(x <= a[i])
    26                 {
    27                     printf("%d %d
    ",a[i],x);
    28                 }
    29             }
    30         }
    31     }
    32 }

      同时,nim博弈转化成sg来理解也是没有问题的,每一堆的sg函数怎么计算的呢?显然对一堆,个数为n的话,因为可以取>=1的任意个数,所以n的后续态为0~n-1的连续整数,那么sg[n]=mex{sg[0],sg[1],...,sg[n-1]}。而sg[0]=0,sg[1]=mex{sg[0]}=mex{0}=1, sg[2]=mex{sg[0],sg[1]}=mex{0,1}=2... 因此可以递推得到sg[n]=n。所以根据sg胜利的条件是所有sg值相异或不为0,这正是nim博弈下胜利的条件。

  • 相关阅读:
    Java第七次作业
    JAVA第六次作业
    JAVA第五次作业
    JAVA第四次作业
    JAVA第三次作业
    JAVA第二次作业
    Java第一次作业
    2017《Java》预备作业02 计科1501刘喆
    2017《JAVA》预备作业 计科1501刘喆
    Java第十次作业--多线程
  • 原文地址:https://www.cnblogs.com/zzyDS/p/5690812.html
Copyright © 2011-2022 走看看