CF 2096 H

CF 2096 H

注意到实为计算:

\[\prod_{i=1}^n(z^{l_i}+z^{l_i+1}+\dots +z^{r_i}) \]

显然我们需要使用 \(FWT\) 进行转化问题,设 \(v(i,j)=(-1)^{|i\cap j|}\)

不妨设 \(F_i(z)=z^{l_i}+z^{l_i+1}+\dots +z^{r_i}\)

\[[z^k]IFWT(FWT\prod_{i=1}^n F_i(z))=\prod_{i=1}^n(\sum_{j=l_i}^{r_i}v(k,j)) \]

\(s(i,j)=\sum_{k=0}^jv(i,k)\)

即,求:

\[\prod_{i=1}^n(s(k,r_i)-s(k,l_i-1)) \]

考虑 \(s\) 怎么求。

注意到对于 \(k\) 而言,如二进制位 \(t\) 上是 \(1\),那么对于 \(x\)\(x\oplus 2^t\) 两者的 \(v\) 值相反。

这启发我们:设 \(t\)\(k\) 的 lowbit,则有 \(s(k,2^{t+1}-1)=0\),以至于更多的循环节,也即 \(\forall c\in \mathbb{N},s(k,c2^{t+1}-1)=0\)

那么就会有:

\[\begin{aligned} s(k,r)&=s(k,\lfloor\frac{r}{2^{t+1}}\rfloor2^{t+1}-1)+\sum_{i=\lfloor \frac{r}{2^{t+1}}\rfloor2^{t+1}}^rv(k,i)\\ &=\sum_{i=\lfloor \frac{r}{2^{t+1}}\rfloor2^{t+1}}^rv(k,i)\\ &=\sum_{i=\lfloor \frac{r}{2^{t+1}}\rfloor2^{t+1}}^rv(\lfloor\frac{k}{2^{t+1}}\rfloor,\lfloor\frac{i}{2^{t+1}}\rfloor)\times v(2^{t+1},i)\\ &=v(\lfloor\frac{k}{2^{t+1}}\rfloor,\lfloor\frac{r}{2^{t+1}}\rfloor)\times \sum_{i=\lfloor \frac{r}{2^{t+1}}\rfloor2^{t+1}}^rv(2^{t+1},i)\\ &=v(\lfloor\frac{k}{2^{t+1}}\rfloor,\lfloor\frac{r}{2^{t+1}}\rfloor)\times \sum_{i=0}^{r\bmod 2^{t+1}}v(2^{t+1},i) \end{aligned} \]

当确定 \(t\) 时,有 \(s(k,r)=v(\lfloor\frac{k}{2^{t+1}}\rfloor,\lfloor\frac{r}{2^{t+1}}\rfloor)\times s(\lfloor\frac{k}{2^{t+1}}\rfloor,r\bmod 2^{t+1})\)

注意到前面就是 \([z^{\lfloor\frac{k}{2^{t+1}}\rfloor}]FWT(z^{\lfloor\frac{r}{2^{t+1}}\rfloor})\),而后面的可以预处理计算。

不妨设:

\[a_i=s(\lfloor\frac{k}{2^{t+1}}\rfloor,r\bmod 2^{t+1}),A_i=\lfloor\frac{r}{2^{t+1}}\rfloor \]

\[b_i=-s(\lfloor\frac{k}{2^{t+1}}\rfloor,(l-1)\bmod 2^{t+1}),B_i=\lfloor\frac{l-1}{2^{t+1}}\rfloor \]

\(l=0\) 时令 \(b_i=B_i=0\)。让 \(k'=\lfloor\frac{k}{2^{t+1}}\rfloor\)

那么 \(s(k,r)-s(k,l-1)=[z^{k'}](a_iz^{A_i}+b_iz^{B_i})\)

也就是说:

\[[z^k]\prod_{i=1}^nFWT(F_i(z))=[z^{k'}]\prod_{i=1}^nFWT(a_iz^A_i+b_iz^{B_i}) \]

考虑求出后面这个多项式。

不妨再分解一下:

\[(a_iz^{A_i}+b_iz^{B_i})=(a_i+b_iz^{A_i\oplus B_i})z^{A_i} \]

然后,我们将指数上相同的多项式进行合并,合并是容易的:

\[(a_1+b_1z^c)(a_2+b_2z^c)=(a_1a_2+b_1b_2+(a_1b_2+a_2b_1)z^c) \]

那么我们就可以将其转化为:设 \(p_i,r_i\) 为合并后的对应 \(z^i\) 这个式的系数。

也就有:

\[\prod_{i=1}^nFWT(a_iz^A_i+b_iz^{B_i})=\prod_{i=0}^{2^{m}-1}FWT(p_i+q_iz^i) \]

那么 \([z^{k'}]\) 的系数是:

\[\prod_{i=0}^{2^m-1}(p_i+v(k',i)q_i) \]

这个东西的计算可以仿照一般的 \(FWT\),维护 \(ad_i=p_i+q_i,de_i=p_i-q_i\),那么在 \(FWT\) 过程中就有:

\[\begin{cases} ad_{x}'=ad_{x}ad_{x+2^t},de_x'=de_xde_{x+2^t}\\ ad_{x+2^{i}}'=ad_{x}de_{x+2^t},de'_{x+2^t}=de_xad_{x+2^t} \end{cases} \]

那么这个题就解决了。

枚举 \(t\),就可以计算一个长度为 \(2^{m-t-1}\) 的多项式,然后将所有 \(lowbit\)\(t\)\(k\) 的答案就算出来了。

最后还原即可。

注意 \(0\) 的值特殊计算。

#include<bits/stdc++.h>
using namespace std;
#define int long long 
#define N 1050500
const int p=998244353;
int le[N],ri[N];
struct node{
	int ad,de;
}f[N],h[N],tmp[N];
int n,m,a[N],val[N],b[N],c[N],d[N],g[N],na[N],nb[N],bit[N];
void sol(){
	cin>>n>>m;g[0]=1;bit[0]=1;
	for(int i=1;i<(1<<m);++i)bit[i]=-bit[i^(i&-i)];
	for(int i=1;i<=n;++i){
		cin>>le[i]>>ri[i];++ri[i];++le[i];
		g[0]=g[0]*(ri[i]-le[i]+1)%p;
	}
	for(int i=0;i<(1<<m);++i){
		val[i]=na[i]=nb[i]=0;
	}
	for(int t=m-1;~t;--t){
		for(int i=0;i<(1<<m);++i)val[i]=bit[(1<<t)&i];
		for(int i=1;i<(1<<m);++i)val[i]+=val[i-1];
		for(int i=0;i<(1<<m);++i)na[i]=1,nb[i]=0;
		for(int i=1;i<=n;++i){
			a[i]=val[(ri[i]-1)%(1<<t+1)],b[i]=le[i]>1?-val[(le[i]-2)%(1<<t+1)]:0;
			c[i]=(ri[i]-1)>>t+1,d[i]=le[i]>1?(le[i]-2>>t+1):0;
			int a1=na[c[i]^d[i]],b1=nb[c[i]^d[i]];
			na[c[i]^d[i]]=a1*a[i]%p+b1*b[i]%p;
			nb[c[i]^d[i]]=a1*b[i]%p+a[i]*b1%p;
			a1=na[c[i]],b1=nb[c[i]];
			na[c[i]]=0ll*a1+1ll*b1;
			nb[c[i]]=a1*1ll+0ll*b1;
		}
		for(int i=0;i<(1<<m-t-1);++i){
			f[i].ad=((na[i]+nb[i])%p+p)%p,f[i].de=((na[i]-nb[i])%p+p)%p,tmp[i]=f[i];
		}
		for(int len=1;len<(1<<m-t-1);len<<=1)for(int j=0;j<(1<<m-t-1);j+=len<<1)for(int k=0;k<len;++k){
			node a=f[j+k],b=f[j+k+len];
			f[j+k].ad=a.ad*b.ad%p,f[j+k].de=a.de*b.de%p;
			f[j+k+len].ad=a.ad*b.de%p;f[j+k+len].de=a.de*b.ad%p;
		}
		for(int k=0;k<(1<<m);++k)if((k&-k)==(1<<t))g[k]=f[k>>t+1].ad%p;
	}
	for(int len=1;len<(1<<m);len<<=1)for(int j=0;j<(1<<m);j+=len<<1)for(int k=0;k<len;++k){
		int x=g[j+k],y=g[j+k+len];
		g[j+k]=(x+y)%p*(p+1>>1)%p;
		g[j+k+len]=(x-y)%p*(p+1>>1)%p;
	}int ans=0;
	for(int i=0,mul=1;i<(1<<m);++i,mul=mul*2ll%p)g[i]=(g[i]*mul%p+p)%p,ans^=g[i];
	cout<<ans<<"\n";
}
signed main(){
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	int T;cin>>T;
	while(T--)sol();
}
posted @ 2025-04-22 22:37  spdarkle  阅读(34)  评论(0)    收藏  举报