loading

AGC061E Increment or XOR

太深刻了,使我的脑子旋转。

题意

给定 \(S,T\),初始 \(x=S\),你可以进行以下操作:

  • \(x\leftarrow x+1\),代价为 \(A\)
  • \(x\leftarrow x\oplus Y_i\),代价为 \(C_i\)。这样的 \(i\) 只有 \(n\) 个。

求使得 \(x=T\) 的最小代价,无解输出 -1

\(n\le 8,S,T<2^{40}\),答案在 long long 范围内。

分析

拿到这道题不出意外的毫无突破口。难点显然在于 \(+1\) 会进位,破坏了异或位间独立的优美性质。考虑从 \(+1\) 操作入手,你注意到如果 \(+1\) 造成了进位,它后面一定会变成一堆 0,而假设进位进到的最高位是第 \(w\) 位,那么 \(w+1\) 位只有异或操作才能产生贡献,再看到 \(n\) 极小,所以状压一下每种操作执行的奇偶性就可以判断合不合法了。考虑从小到大 dp,假设 \(+1\) 将位进到了第 \(d\) 位,那么 \([0,d-1]\) 这些位一定全零,这是一个子结构,所以本质有用的起点和终点只有两种。

\(f_{i,s,t,msk}\) 表示考虑到第 \(i\) 位,钦定第 \(i\)除了最后一次操作外不会向第 \(i+1\) 位进位,初始为 \(S\) 或者 \([0,i-1]\) 位上全 0,终点为 \(T\) 或者 \([0,i-1]\) 位上全 1,并且若 \(t=1\) 要钦定操作过后进行一次 \(+1\) 进位(算上进位的代价,也就是实际上最终变为了全 0 且向最高位进一位),若 \(t=0\) 则钦定过程中不能有进位

转移有两种:

  • 这一位上不进位,那么枚举起点和终点,看看起点经过异或操作能否到达终点状态。
  • 这一位上进位,则转移形如 \(f_{i,s,1,msk_1}+f_{i,1,1,msk_2}+\cdots+f_{i,1,1,msk_{k-1}}+f_{i,1,t,msk_k}=f_{i+1,s,t,msk_1\oplus msk_2\oplus \cdots\oplus msk_k}\),转移过程中需要满足通过异或操作能在不进位的前提下从起始状态到达最终状态,例如 \(f_{i,1,1,msk_{j}}\) 需要满足 \(msk_j\) 异或操作能从 100000... 到达 011111...。发现这个过程相当于最短路,写个 \(O(n^2)\) dij 即可。

最终答案就是 \(f_{40,0,0,msk}\)。总时间复杂度 \(O(2^{2n}\log V)\)

具体转移细节可以看代码。

int n,S,T,A,b[10],w[10];
int xum[1<<8],sum[1<<8];
//将[0,i-1]位复原,起点,终点,异或奇偶性,保证进位只进到第i位 
int f[41][2][2][1<<8];
int dis[1<<8];
bool vis[1<<8];
inline void solve_the_problem(){
	n=rd(),S=rd(),T=rd(),A=rd();
	rep(i,1,n)b[i]=rd(),w[i]=rd();
	rep(msk,0,(1<<n)-1)rep(i,1,n)if((msk>>(i-1))&1)xum[msk]^=b[i],sum[msk]+=w[i]; 
	mem(f,0x3f);
	rep(i,0,1)rep(j,0,1)rep(msk,0,(1<<n)-1)f[0][i][j][msk]=sum[msk]+j*A;
	rep(d,0,39){
		rep(s,0,1)rep(t,0,1){
			int si=s?0:((S>>d)&1),ti=t?1:((T>>d)&1);
			rep(msk,0,(1<<n)-1)if((si^ti)==((xum[msk]>>d)&1))ckmn(f[d+1][s][t][msk],f[d][s][t][msk]); 
		}
		rep(s,0,1){
			int si=s?0:((S>>d)&1);
			rep(msk,0,(1<<n)-1)dis[msk]=llinf,vis[msk]=0;
			rep(msk,0,(1<<n)-1)if(((xum[msk]>>d)&1)==si)ckmn(dis[msk],f[d][s][1][msk]);
			while(1){
				int msk=-1,mn=llinf;
				rep(i,0,(1<<n)-1)if(!vis[i]&&ckmn(mn,dis[i]))msk=i;
				if(msk==-1)break;
				vis[msk]=1;
				rep(msk2,0,(1<<n)-1){
					if((xum[msk2]>>d)&1)ckmn(dis[msk^msk2],dis[msk]+f[d][1][1][msk2]);
					rep(t,0,1){
						int ti=t?1:((T>>d)&1);
						if(((xum[msk2]>>d)&1)==(ti^1))ckmn(f[d+1][s][t][msk^msk2],dis[msk]+f[d][1][t][msk2]);
					}
				}
			}
		}
	}
	int ans=llinf;
	rep(i,0,(1<<n)-1)ckmn(ans,f[40][0][0][i]);
	if(ans==llinf)PW;
	else write(ans);
}
posted @ 2026-01-24 15:55  dcytrl  阅读(8)  评论(0)    收藏  举报