Codeforces 1704 F Colouring Game 题解 (结论,SG函数)

题目链接

首先看R和B的数量不等的情况(很多博弈题都是先比较两种物品的数量,相等的情况再用SG函数之类的技巧),结论是R多Alice必赢,B多Bob必赢。证明:来看R比B多的情况,定义两人的"差距"为当前R的数量减B的数量。发现Alice操作只可能让差距不变或变小,Bob操作只可能让差距不变或变大。定义"一轮游戏"为Alice先操作一次,Bob再操作一次的过程。如果一轮开始前还有"RB"或"BR",那么Alice就随便找一个RB或BR涂了,这一轮差距就肯定不会变小,Alice仍然保持领先;如果没有RB或BR,就看有没有RW或WR,如果有就随便找一个涂了,由于此时没有RB、BR所以Bob也只能涂BW和WB,因此差距仍然不会减小;只有RR的情况是不存在的,除非整个序列全是R,但是这种情况Alice本来就会赢。对于B比R多的情况也是类似(Alice第一次操作后B显然还比R多,所以就变成和上面一样的情况了)。

R和B相等的情况,两人都只能涂RB或BR,否则会导致R和B不相等,根据上面的结论操作这步的人就输了。所以问题变成:两个人每次可以挑相邻的两个RB或BR涂白,不能操作的人输。把序列分成若干段,每段都是极长的RBRBRB交错的区间。被涂的位置肯定是被完全包含在某个段内部,不可能横跨两个段的,因为这样不可能是RB或BR。发现每一段的内部都构成了一个公平的有向图游戏,可以对每一段求SG函数再异或起来得到答案。一个长为i的段的SG函数为:\(sg_i=mex_{l+r=i-1}(sg_l\bigoplus sg_r)\),其中\(\bigoplus\)表示异或。这玩意儿看上去像卷积,但其实不太能用多项式技巧求。正确的求法居然是:sg值除了前几项,后面的均以34为循环节,所以暴力求出前若干项(比如1000)就行了。真的是很无聊(不知道这题怎么过cf审核的),但是也要了解一下,防止以后再出现这种题。

点击查看代码
#include <bits/stdc++.h>

#define rep(i,n) for(int i=0;i<n;++i)
#define repn(i,n) for(int i=1;i<=n;++i)
#define LL long long
#define pii pair <int,int>
#define fi first
#define se second
#define mpr make_pair
#define pb push_back

void fileio()
{
  #ifdef LGS
  freopen("in.txt","r",stdin);
  freopen("out.txt","w",stdout);
  #endif
}
void termin()
{
  #ifdef LGS
  std::cout<<"\n\nEXECUTION TERMINATED";
  #endif
  exit(0);
}

using namespace std;

int sg[500010];

int dfs(int pos)
{
  if(sg[pos]>-1) return sg[pos];
  if(pos<2) return sg[pos]=0;
  map <int,int> mp;
  rep(i,pos-1)
  {
    int l=i,r=pos-l-2;
    int val=dfs(l)^dfs(r);
    mp[val]=1;
  }
  rep(i,1000) if(mp.find(i)==mp.end()) return sg[pos]=i;
}

int t,n;
string s;
char c[500010];

int main()
{
  fileio();

  rep(i,1005) sg[i]=-1;
  dfs(1000);
  for(int i=1001;i<=500005;++i) sg[i]=sg[i-34];
  cin>>t;
  rep(tn,t)
  {
    scanf("%d%s",&n,c);s=c;
    int cr=0,cb=0;
    rep(i,n) if(s[i]=='R') ++cr;else ++cb;
    if(cr>cb) puts("Alice");
    else if(cb>cr) puts("Bob");
    else
    {
      int ans=0;
      rep(i,n)
      {
        int p=i;
        while(p+1<n&&s[p+1]!=s[p]) ++p;
        ans^=sg[p-i+1];i=p;
      }
      puts(ans ? "Alice":"Bob");
    }
  }

  termin();
}
posted @ 2023-01-10 11:08  LegendStane  阅读(159)  评论(1)    收藏  举报