博弈论 Staircase Nimm Games

为什么叫staircase?肯定跟楼梯有关系。还是一个游戏,规则如下:

    有N堆石子放在N级楼梯上,楼梯编号为0..N-1(最下面那个是0好了),每堆有a[n]个石子。两人轮流游戏,每次将任意堆中的任意个石子移动到它下面那一层楼梯上。直到所有石子都移动到0号(就是楼底),那个人就赢了。仍然是问必胜策略。

     然后用昨天学到的方法整理一下:当石子全部在0号楼梯的状态时P-position;当石子全部在1上的(也可以在0 1上面都有)是N-position。当0,1,2均存在石子时,又是两种情况:①a[1]=a[2],则先手必败;②a[1]≠a[2],则先手可以通过移动多的使a[1]=a[2]则先手必胜。(这个跟昨天一样嘛。。。)

    如果当前是N-position,那么一定是从奇数楼梯放入偶数楼梯中。那么对于奇数楼梯的状态有两种:①从偶数楼梯放到奇数楼梯;②从奇数楼梯放入偶数楼梯。

    所以,保证先手取奇数楼梯中的石子,使得异或和为0,则可以最后取走1中的石子。

    算法:将奇数楼层的状态异或,和为0则先手必败,否则先手必胜。

    

    首先我们要证明为什么奇楼梯石子异或的NIM和为0,则先手必败。

        一、如果奇楼梯上都没有放石子,只有偶楼梯上放有石子。

      这时,后手有必胜策略。先手从楼梯上移x个石子到奇楼梯,那么后手就把奇楼梯上的这x个石子移到偶楼梯上,这样做下去,后手一        

    定能把最后的石子从奇楼梯1上移到偶楼梯0上。所以先手必败。

        二、如果有两个奇楼梯上放有相同的石子。

      这时,后手有必胜策略。先手从奇楼梯a上拿走x个石子,后手就从奇楼梯b上拿走x个石子。这样,后手一定能做到最后一个把奇楼梯

    上的石子移到偶楼梯0上。

        根据游戏的组合,我们可以得出结论,只要奇楼梯的异或和为0,则先手必败。

 

        然后,我们要证明为什么奇楼梯石子异或和不为0时,则先手必胜。

        先手必胜状态下的子状态存在先手必败状态,所以,我们要证明的是当奇楼梯异或和不为0的时候,我们通过一次操作,可以保证奇楼         

    梯异或和为0。

        我们设奇楼梯上的石子数为a1,a2,a3,…,ai,…,an。

        如果a1 xor a2 xor a3 xor…xor ai xor …xor an=k!=0,若操作后使得ai'=ai xor k,那么a1 xor a2 xor a3 xor…xor ai' xor…xor an=0。

在a1,a2,a3,…an中一定可以找到ai使得ai'=ai xor k<ai。(上一篇这个我已经证明了)

    证毕。

 

     题目:POJ1704

Georgia and Bob
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 3943 Accepted: 977

Description

Georgia and Bob decide to play a self-invented game. They draw a row of grids on paper, number the grids from left to right by 1, 2, 3, ..., and place N chessmen on different grids, as shown in the following figure for example: 

Georgia and Bob move the chessmen in turn. Every time a player will choose a chessman, and move it to the left without going over any other chessmen or across the left edge. The player can freely choose number of steps the chessman moves, with the constraint that the chessman must be moved at least ONE step and one grid can at most contains ONE single chessman. The player who cannot make a move loses the game. 

Georgia always plays first since "Lady first". Suppose that Georgia and Bob both do their best in the game, i.e., if one of them knows a way to win the game, he or she will be able to carry it out. 

Given the initial positions of the n chessmen, can you predict who will finally win the game? 

Input

The first line of the input contains a single integer T (1 <= T <= 20), the number of test cases. Then T cases follow. Each test case contains two lines. The first line consists of one integer N (1 <= N <= 1000), indicating the number of chessmen. The second line contains N different integers P1, P2 ... Pn (1 <= Pi <= 10000), which are the initial positions of the n chessmen.

Output

For each test case, prints a single line, "Georgia will win", if Georgia will win the game; "Bob will win", if Bob will win the game; otherwise 'Not sure'.

Sample Input

2
3
1 2 3
8
1 5 6 7 9 12 14 17

Sample Output

 Bob will win
 Georgia will win

  这个题很猥琐。我不是说它算法猥琐。我当时看到那个图之后直接就写了个Staircase Nim,连题都没看,然后交上去:WA了……

  连续好几遍:继续WA

  后来读了读题,发现惊天秘密啊!问题的关键:每个格子只能放一个棋子,而且给出的pn并不是棋子的个数,而是每个棋子的位置……

  根据每个格子只能放一个棋子这个性质,我们可以把一个放有棋子的格子跟它之前的所有空格子合并成一个格子,像这样

              (红色表示有棋子放置)

  分组之后

       

  为什么要这么分呢?因为,如果对手将一个棋子向前移动,那么你一定可以将后面的一个棋子向前移动相同的步数。所以,空格子的数量对于结果是没有影响的。

  然后对于与处理之后的数据,我们直接按照Staircase Nimm来做就可以了。

  那个……再插一句……此题因为数据经过我们的预处理,那么他不是一个简单的Nimm,格子的数量会影响我们的决策。

  当有棋子的格子(n)数量为偶数时,经过分析,我们发现奇数行的决策对于结果不会产生影响,所以将偶数行异或。

  反之,则把奇数行异或。

var p:array[1..10000]of longint;
    t,n,i,ans:longint;

procedure quicksort(head,tail:longint);
var i,j,x,t:longint;
begin
   i:=head;j:=tail;x:=p[random(tail-head+1)+head];
   repeat
     while p[i]<x do inc(i);
     while p[j]>x do dec(j);
     if i<=j then
       begin
         t:=p[i];p[i]:=p[j];p[j]:=t;
         inc(i);dec(j);
       end;
   until i>j;
   if i<tail then quicksort(i,tail);
   if j>head then quicksort(head,j);
end;

begin
  readln(t);
  while t>0 do
    begin
      dec(t);
      readln(n);
      for i:=1 to n do read(p[i]);
      quicksort(1,n);
      for i:=n downto 1 do p[i]:=p[i]-p[i-1]-1;
      ans:=p[1];
      for i:=1 to n do
        if i mod 2=1 then ans:=ans xor p[i];
      if ans=0 then writeln('Bob will win')
        else writeln('Georgia will win');
    end;
  readln;
end.
原文地址:https://www.cnblogs.com/Delostik/p/1972021.html