CF2096H - Wonderful XOR Problem

题目链接

大概想法是把所有 \([l _ i, r _ i]\) 通过 FWT 转化成点值后,对应位置乘起来,再 IFWT 回去。

但这样时间复杂度比较爆,考虑 FWHT,记 \(s (j, k) = (-1) ^ {\operatorname{popcount} (j \operatorname \& k)}\),一个 \([l _ i, r _ i]\) 对位置 \(k\) 的乘积贡献为 \(\sum _ {j = l _ i} ^ {r _ i} s (j, k)\)

简化上式,首先可以把 \([l _ i, r _ i]\) 差分掉,先只考虑 \(r _ i\),记 \(f (k, r)\)\([0, r]\) 对位置 \(k\) 的贡献,\(\operatorname {lowbit (k)}\)\(2 ^ p\),那么 \(r _ i \ge 2 ^ {p + 1}\)\(f (k, r) = f (k, r - 2 ^ {p + 1})\),因为第 \(p\) 位贡献了 \(2 ^ p\)\(1\)\(2 ^ p\)\(-1\) 抵消掉了。故可以把 \(r\) 先模掉 \(2 ^ {p + 1}\)

因为 \(s (j, k)\) 本质上是乘法可以拆,则 \(f (k, r) = s (\lfloor r / 2 ^ {p + 1} \rfloor, \lfloor k / 2 ^ {p + 1} \rfloor) \times \sum _ {j = 0} ^ r s (j, 2 ^ p)\)。故外层枚举 \(p\),再考虑上 \(l _ i - 1\) 的贡献,区间 \([l _ i, r _ i]\) 对位置 \(k' = \lfloor k / 2 ^ {p + 1} \rfloor\) 的贡献可以写成 \(a _ i x ^ {c _ i} + b _ i x ^ {d _ i}\) 的形式。

明确一下目标,枚举 \(p\) 之后,现在我们要对每个 \(k'\) 求出 \([x ^ {k'}] \prod (a _ i x ^ {c _ i} + b _ i x ^ {d _ i})\)。一般性地,先把 \(a _ i x ^ {c _ i} + b _ i x ^ {d _ i}\) 化成 \((a _ i x ^ {c _ i \oplus d _ i} + b _ i) x ^ {d _ i}\) 形式,把所有 \(x ^ {d _ i}\) 提出来最后再乘。对于相同的 \(t\),合并所有 \({a _ i} x ^ t + b _ i\) 是容易的。

考虑如何对于每个 \(k'\) 求出 \(\prod _ {t = 0} ^ {2 ^ {m - p}} (s (t, k') A _ t + B _ t)\)。设计递归函数 \(F (X, Y)\),其中 \(X _ i = A _ i + B _ i\)\(Y _ i = -A _ i + B _ i\),然后把 \(X, Y\) 分成前后两半 \(X _ 0, X _ 1, Y _ 0, Y _ 1\),你发现 \(F (X, Y) = F (X _ 0 X _ 1, Y _ 0 Y _ 1) + x ^ {2 ^ {m - p - 1}} F (X _ 0 Y _ 1, Y _ 0 X _ 1)\) 递归下去,其中乘法表示对应位置相乘。最后对于所有 \(p\) 都做完后再 IFWT 回去即可。

对于每个 \(p\) 复杂度是等比数列求和的。时间复杂度 \(\text O (nm + 2 ^ m m)\)

#include<cstdio>
#include<algorithm>
#define N 20
#define PN ((1<<18)+5)
using namespace std;

const int mod=998244353,inv2=(mod+1)/2;
int T,n,m,l[PN],r[PN],a[N][PN],b[N][PN],c[N][PN],xorsum[N];
int X[N][PN],Y[N][PN],F[N][PN],f[PN];
inline void add(int &x,long long y) {x=(x+y)%mod;}
int calc(int x,int p) {
	return x<p?x+1:p-(x-p+1);
}
void solve(int k) {
	if(!k) {
		F[k][0]=X[k][0];
		return;
	}
	int l=1<<k-1;
	for(int i=0;i<l;i++) X[k-1][i]=1ll*X[k][i]*X[k][l+i]%mod;
	for(int i=0;i<l;i++) Y[k-1][i]=1ll*Y[k][i]*Y[k][l+i]%mod;
	solve(k-1);
	for(int i=0;i<l;i++) F[k][i]=F[k-1][i];
	for(int i=0;i<l;i++) X[k-1][i]=1ll*X[k][i]*Y[k][l+i]%mod;
	for(int i=0;i<l;i++) Y[k-1][i]=1ll*Y[k][i]*X[k][l+i]%mod;
	solve(k-1);
	for(int i=0;i<l;i++) F[k][l+i]=F[k-1][i];
}
void IFWT(int f[N],int len) {
	for(int i=1;i<len;i<<=1)
		for(int j=0;j<len;j+=i<<1)
			for(int k=j;k<j+i;k++) {
				int x=f[k],y=f[k+i];
				f[k]=1ll*(x+y)*inv2%mod,f[k+i]=1ll*(x-y+mod)*inv2%mod;
			}
}
int main() {
	scanf("%d",&T);
	while(T--) {
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++) {
			scanf("%d%d",&l[i],&r[i]),l[i]--;
			for(int j=0;j<m;j++) {
				a[j][i]=calc(r[i]&(1<<j+1)-1,1<<j);
				b[j][i]=~l[i]?(-calc(l[i]&(1<<j+1)-1,1<<j)+mod)%mod:0;
			}
		}
		for(int i=0;i<m;i++) {
			xorsum[i]=0;
			for(int j=1;j<=n;j++) {
				c[i][j]=r[j]>>i+1;
				if(~l[j]) c[i][j]^=l[j]>>i+1,xorsum[i]^=l[j]>>i+1;
			}
		}
		f[0]=1;
		for(int i=1;i<=n;i++) f[0]=1ll*f[0]*(r[i]-l[i])%mod;
		for(int i=0;i<m;i++) {
			int k=m-i-1;
			for(int j=0;j<1<<k;j++) X[k][j]=0,Y[k][j]=1;
			for(int j=1;j<=n;j++) {
				int idx=c[i][j],u=X[k][idx],v=Y[k][idx];
				X[k][idx]=(1ll*u*b[i][j]+1ll*v*a[i][j])%mod;
				Y[k][idx]=(1ll*u*a[i][j]+1ll*v*b[i][j])%mod;
			}
			int idx=xorsum[i]; swap(X[k][idx],Y[k][idx]);
			for(int j=0;j<1<<k;j++) {
				int u=X[k][j],v=Y[k][j];
				X[k][j]=(v+u)%mod,Y[k][j]=(v-u+mod)%mod;
			}
			solve(k);
			for(int j=0;j<1<<k;j++) f[(j<<1|1)<<i]=F[k][j];
		}
		IFWT(f,1<<m);
		long long ans=0,pw2=1;
		for(int i=0;i<1<<m;i++)
			ans^=f[i]*pw2%mod,pw2=pw2*2%mod;
		printf("%lld\n",ans);
	}
	return 0;
}
posted @ 2026-01-12 17:05  yemuzhe  阅读(0)  评论(0)    收藏  举报