zoukankan      html  css  js  c++  java
  • 2016多校联合训练1 B题Chess (博弈论 SG函数)

          题目大意:一个n(n<=1000)行,20列的棋盘上有一些棋子,两个人下棋,每回合可以把任意一个棋子向右移动到这一行的离这个棋子最近的空格上(注意这里不一定是移动最后一个棋子),不能移动到棋盘外,不能移动了就算输,两个人都用最优策略,问先手是否有必胜策略。

          这题显然就是SG函数了吧。行与行之间互不影响,所以可以看成n个子游戏,求出它们各自的SG函数然后异或一下就可以了。我们发现只有20列,2^21=2097152,所以我们可以先把行的所有情况的SG函数预处理出来,然后每次询问O(1)就行了。

    代码如下:

    var
      t,i,j,m,v,c,res,n,cl:longint;
      cnt:array[0..22]of longint;
      a:array[0..10000000]of longint;
    
    procedure calc(x,c:longint);
    begin
      dec(x,1<<(c-1));inc(c);
      while c<=20 do
      begin
        if x and (1<<(c-1))=0 then break;
        inc(c);
      end;
      if c>20 then exit;
      inc(x,1<<(c-1));
      cnt[a[x]]:=1;
    end;
    
    procedure init;
    begin
      for i:=(1<<20)-1 downto 0 do
      begin
        fillchar(cnt,sizeof(cnt),0);
        for j:=1 to 20 do
        if i and (1<<(j-1))<>0 then calc(i,j);
        for j:=0 to 20 do
        if cnt[j]=0 then
        begin
          a[i]:=j;
          break;
        end;
      end;
    end;
    
    procedure solve;
    begin
      readln(n);res:=0;
      for i:=1 to n do
      begin
        c:=0;
        read(m);
        for j:=1 to m do
        begin
          read(v);
          c:=c or(1<<(v-1));
        end;
        res:=res xor a[c];
      end;
      if res<>0 then writeln('YES')
      else writeln('NO');
    end;
    
    begin
      init;
      readln(t);
      while t>0 do
      begin
        dec(t);
        solve;
      end;
    end.
    View Code
  • 相关阅读:
    (6)sql/puls
    (5)Toad for oracle使用
    (4)oracle连接工具和配置监听
    (3)oracle建用户、建表、权限、命名空间
    (2)oracle服务、建库
    (1)oracle安装、卸载、启动、关闭、登陆以及同时遇到的问题
    (1)C#工具箱-公共控件1
    Tarjan
    最小表示法
    STL
  • 原文地址:https://www.cnblogs.com/Sakits/p/5770412.html
Copyright © 2011-2022 走看看