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)\)

  1. 删掉比 \(highbit(a)\) 更大的二进制位
  2. 找到 \(\max_t (a)_t=1,(x)_t=0\),将 \(\le t\)\(x\) 的零位全部删掉,并且将 \(a\) 对应的位变成 \(1\)

考虑这样的一个 \(a\)\(sg\) 函数值。

它能够转移到什么样的状态?

显然 \(sg\) 值与二进制下最高位有关系,不妨打表,可以发现

  1. \(sg(2^k-1)=k\)
  2. \(sg(2^k-2)=0,k\ge 1\)
  3. \(sg(2^k)=k\oplus 1\)
  4. 其余值都是 \(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]--;
}
posted @ 2024-11-10 19:17  spdarkle  阅读(5)  评论(0编辑  收藏  举报