[??记录]AT3727 [ARC087C] Prefix-free Game

command_block

2021-05-10 10:21:29

Personal

**题意** : 本题中,字符集为 $\{\texttt{0},\texttt{1}\}$。 给出 $L$ ,定义一个字符串集合 $S$ 是好的,当且仅当 : - $S$ 中的字符串长度在 $1\sim L$ 之间。 - $S$ 中的任意两个字符串,都不能满足一者为另一者的前缀。 给出一个好的字符串集合 $S$。 A,B 博弈。两人轮流操作,每次可以向 $S$ 中加入一个字符串,无法操作者输。 问是否先手必胜。 $n\leq 10^5$ ,时限$\texttt{2s}$。 ------------ 我们先用 $S$ 内的字符串建立字典树。 那么,每个串的前缀和子树都不能再选择,剩下的区域均为满二叉树。 考虑使用 $\rm SG$ 函数。 记层数为 $h$ 的满二叉树的 $\rm SG$ 值为 $f[h]$。 利用 $\text{Muti-SG}$ 的分析技巧,不难列出递推式 : $$ \begin{aligned} f[h]=&{\rm mex}\Big\{\\ &0,\\ &f[h-1],\\ &f[h-1]\oplus f[h-2],\\ &f[h-1]\oplus f[h-2]\oplus f[h-3]\\ &\cdots\\ &f[h-1]\oplus f[h-2]\oplus ... \oplus f[1]\\ \Big\}&\\ \end{aligned} $$ 打表可以发现 $f[h]={\rm lowbit}(h)$。 ```cpp #include<algorithm> #include<cstring> #include<cstdio> #define MaxN 100500 #define ll long long using namespace std; struct Node{int t[2];}a[MaxN]; #define lbit(x) ((x)&-(x)) ll ans,L; void dfs(int u,int dep) { if (!u){ans^=lbit(L-dep+1);return ;} dfs(a[u].t[0],dep+1);dfs(a[u].t[1],dep+1); } int n,tn;char s[MaxN]; int main() { scanf("%d%lld",&n,&L);tn=1; for (int t=1;t<=n;t++){ scanf("%s",s); int len=strlen(s),u=1; for (int i=0;i<len;i++){ s[i]-='0'; if (!a[u].t[s[i]])a[u].t[s[i]]=++tn; u=a[u].t[s[i]]; } }dfs(1,0); printf(ans ? "Alice" : "Bob"); return 0; } ```