题面
考虑把所有输入的字符串看成一棵二叉Trie树(深度为
L
),那么一个字符串所在的点到根节点的路径及其子树中不能有其他的点。
现在双方的操作就是在Trie树上轮流放点,也就是取走一个以
所以取深度为
X
的树的
SG(X)=mex{0,SG(X−1),SG(X−1)xorSG(X−2),...,SG(X−1)xor...xorSG(1)}
打表发现:
SG(X)=lowbit(X)
写一棵Trie树把一开始能取的树找出来,把它们的 SG 函数值异或起来就可以判断了。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int maxn=200010;
int n,tr[maxn][2],bg[maxn],tot=1;ll L;
bool num[100];
char s[maxn];
int lowbit(ll x)
{
int r=0;
for(;!(x&1);r++,x>>=1);
return r;
}
void ins(int v,int id,int d,int len)
{
if(tr[v][s[bg[id]+d-1]-'0']==0) tr[v][s[bg[id]+d-1]-'0']=++tot;
if(d!=len) ins(tr[v][s[bg[id]+d-1]-'0'],id,d+1,len);
}
void dfs(int v,int d)
{
for(int k=0;k<=1;k++)
if(tr[v][k]==0) {if(L-d>0) num[lowbit(L-d)]^=1;}
else dfs(tr[v][k],d+1);
}
int main()
{
scanf("%d%lld",&n,&L);
int top=0;
for(int i=1;i<=n;i++)
{
bg[i]=top+1;
scanf("%s",s+bg[i]);
top+=strlen(s+bg[i]);
ins(1,i,1,strlen(s+bg[i]));
}
dfs(1,0);
for(int i=0;i<=60;i++) if(num[i]) {puts("Alice");return 0;}
puts("Bob");
return 0;
}