CF2027E2
显然独立求出每堆的 \(SG(a,x)\) 即可。
什么时候无法下棋?当且仅当不存在一个\(x\) 的子集满足其 \(\le a_i\),也就是 \(lowbit(x)>a_i\)
但是同时,比 \(a_i\) 更大的二进制位是无法动弹的,可以直接删去
所以这时候我们就保证了末状态一定是零。
同时对于 \(a,x\) 二进制下同为零的位也可以删去,这样我们保证了 \(a|x=2^k-1\)
同时我们找到最大的 \(a\) 为 \(1\),\(x\) 为 \(0\) 的二进制位,这说明比它更低的位的 \(a\),可以变成全是 \(1\) 的,同时缩掉这一位。
如果不存在,那么说明 \(a\) 是 \(x\) 的子集,那么 \(x=2^k-1\),同时我们知道 \(a,x\) 最高位相同,所以这个时刻,我们就可以直接用 \(a\) 来表达 \(x\)。
通过反复进行调整,可以发现最开始的最大的 \(a\) 为 \(1\),\(x\) 位 \(0\) 的二进制位往下,\(x\) 所有为零的位都会被缩掉,因此通过此操作,我们可以将局面间接转化为:\((a,2^{\lfloor\log_2 a\rfloor+1}-1)\)
- 删掉比 \(highbit(a)\) 更大的二进制位
- 找到 \(\max_t (a)_t=1,(x)_t=0\),将 \(\le t\) 的 \(x\) 的零位全部删掉,并且将 \(a\) 对应的位变成 \(1\)。
考虑这样的一个 \(a\) 的 \(sg\) 函数值。
它能够转移到什么样的状态?
显然 \(sg\) 值与二进制下最高位有关系,不妨打表,可以发现
- \(sg(2^k-1)=k\)
- \(sg(2^k-2)=0,k\ge 1\)
- \(sg(2^k)=k\oplus 1\)
- 其余值都是 \(highbit(x)+1\)
若SG函数打表无法看出明显规律,不妨先想办法划分等效状态,这可以简化找到规律的难度
发现 \(sg\) 值全是 \(log\) 级别,我们做 E2 就是只需要算出每个 \(sg\) 值被取出的次数
如何优化我们的调整,亦或者用更简洁的语言表达?
首先是 \(x\&=2^{highbit(a)+1}-1\)
如果我们先不删掉同为零的位,而是放任不管,那么这个位数是 \(popcount((2^{highbit(a)+1}-1)\oplus (x|a))\)
然后至于最大的 \(a\) 为 \(1\),\(x\) 为零,应当是 \(rev(x)\& a\) 的最高位吧。
接着我们进行的变化是考虑这个位往下的所有 \(x\) 的 \(0\) 位,这是需要删掉的
往上的位不变。
比较麻烦啊,能不能直接算
考虑数位 \(dp\),发现贡献只需要考虑 \(2^k,2^k-1,2^k-2\) 和其他值,不妨设 \(dp_{dep,flg,tag,j,k,d}\) 表示已经填了二进制下不低于 \(dep\) 的位,此时有无最高位限制,是否已经填过一个 \(a\) 取 \(1\),\(x\) 取零的二进制位,当前的 \(a'\) 二进制下共出现过 \(j\) 个 \(1\),当前的 \(x'\) 的位数已经确定了 \(k\),同时 \(2^k-a'=d\)。
因为记录差不容易处理 \(2^t\) 的情形,所以额外记录了一个位数,因此有 \(j\) 只需要记录到 \(2\),\(d\) 只需要记录到 \(3\) 即可。
初始化 \(dp_{31,1,0,0,0,1}=1\) ,分类讨论进行转移。
void dp(){
memset(f,0,sizeof f);
f[31][1][0][0][0][1]=1;
for(int now=31;now;--now)for(int flg:{0,1})for(int ap:{0,1})
for(int bit:{0,1,2})for(int c=0;c+now<=31;++c)for(int d:{0,1,2,3}){
int v=f[now][flg][ap][bit][c][d];
if(!v)continue;
int ok=(now-1<=ha);
int va=(A>>now-1)&1,vb=(B>>now-1)&1;
if(!ok){
f[now-1][flg&(vb==0)][ap][bit][c][d]+=v;
if(!flg||vb)f[now-1][flg][ap][bit][c][d]+=v;
continue;
}
int up=flg?vb:1;
for(int i=0;i<=up;++i){
if(!va&&!i)f[now-1][flg&(vb==i)][ap][bit][c][d]+=v;
else if(!va&&i){
if(ap)f[now-1][flg&(vb==i)][ap][min(bit+1,2ll)][c+1][min(3ll,max(0ll,(d<<1)-1))]+=v;
else f[now-1][flg&(vb==i)][ap][bit][c+1][min(3ll,d<<1)]+=v;
}
else if(va&&!i)f[now-1][flg&(vb==i)][1][bit][c][d]+=v;
else f[now-1][flg&(vb==i)][ap][min(2ll,bit+1)][c+1][min(3ll,max(0ll,(d<<1)-1))]+=v;
}
}
for(int flg:{0,1})for(int ap:{0,1})for(auto bit:{0,1,2})for(int c=0;c<=31;++c)for(int d=0;d<4;++d)if(f[0][flg][ap][bit][c][d]){
int sg=0;
if(d==0)sg=c^1;
else if(d==2)sg=0;
else sg=c;
if(!c)sg=0;
if(bit==0)sg=0;
else if(bit==1&&c)sg=(c-1)^1;
g[sg]+=f[0][flg][ap][bit][c][d];
}
g[0]--;
}