题目大意::给定长度为nn的数列a[]a[],定义f(l,r)=i=lra[i]f(l,r)=\oplus^r_{i=l}a[i],求下式:

1l1r1l2r2l3r3nf(l1,r1)f(l2,r2)f(l3,r3)\sum\limits_{1\le l1\le r1 \le l2 \le r2 \le l3 \le r3 \le n} f(l1,r1)*f(l2,r2)*f(l3,r3)
1n2105,1m2105其中1\le n\le 2*10^5,1\le m \le 2*10^5



解题思路:可以逐位考虑,分别计算贡献。
--------首先可以考虑计算1l1r1nf(l1,r1)\sum\limits_{1\le l1\le r1 \le n}f(l1,r1)
sis_i表示第i个数对答案的贡献,preipre_i为序列的异或前缀和,由异或的性质可知若preipre_i二进制下第bitbit位为11,则需要寻找j=1i1prej=0\sum^{i-1}_{j=1}pre_j=0,才会对答案有贡献,显然这是可以预处理的。
此题: 链接


参考代码:

#define LL long long
using namespace std;
const int M=1e5+7;
const LL Mod=998244353;
int n;
LL anq=0;
LL a[M],s[M],pre[M],P[3];
int main(){
	ios::sync_with_stdio(false);
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	pre[0]=0;
	pre[1]=a[1];
	for(int i=2;i<=n;i++){
		pre[i]=pre[i-1]^a[i];
	}
	for(int bit=0;bit<=20;bit++){
		P[0]=1;P[1]=0;
		for(int i=1;i<=n;i++){
			if((pre[i]>>bit)&1){
				 s[i]=P[0];  P[1]++;
			} else {
				 s[i]=P[1];  P[0]++;
			}
			anq=anq+s[i]*(1<<bit);
		}
	}
	cout<<anq<<"\n";
}

接下来,可以考虑求1l1r1l2r2nf(l1,r1)f(l2,r2)\sum\limits_{1\le l1\le r1 \le l2 \le r2 \le n}f(l1,r1)*f(l2,r2)
首先还是考虑拆位。设s[k][i]kis[k][i]表示考虑第k个区间时该区间右端点为i时的贡献,考虑当r2r2固定时,可以枚举l2l2,如果此区间(l2,r2)(l2,r2)在此位上异或值为11,那么对答案贡献便为s[1][l21]s[1][l2-1],即第一区间的右端点在(l21)(l2-1)上。因而可以考虑随着l2l2增 大维护数组P0,P1P_0,P_1表示该位上前缀异或和为0011s1,l2s_{1,l2}的贡献和。
此题k=3,同理可推
注意到s[k][i]s[k1][..]s[k][i]只与s[k-1][..]有关,故可以采用滚动数组

参考代码:

#define LL long long
using namespace std;
const int M=2e5+7;
const LL Mod=998244353;
int n;
LL anq=0;
LL a[M],s[M],pre[M],P[3],ss[M];
int main(){
	ios::sync_with_stdio(false);
	cin>>n;
	s[0]=1;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		pre[i]=pre[i-1]^a[i];
		s[i]=1;
	}
	for(int k=1;k<=3;k++){
		for(int bit=0;bit<=30;bit++){
			P[0]=P[1]=0;
			if(k==1) P[0]=1; //P[x=0/1] 表示之前在 x 前放 k-1 个不相交的区间,所有方案下这些区间的权值和 
		    for(int i=1;i<=n;i++){
			    ss[i]=(ss[i]+(P[((pre[i]>>bit)&1)^1]<<bit))%Mod;
			    P[(pre[i]>>bit)&1]=(1ll*P[(pre[i]>>bit)&1]+s[i])%Mod;
			    //cout<<k<<" "<<bit<<" "<<i<<":"<<P[0]<<" "<<P[1]<<" "<<ss[i]<<"\n";
		    }
	    }
		s[0]=0;
		for(int i=1;i<=n;i++){
		    s[i]=(s[i-1]+ss[i])%Mod;
		    ss[i]=0;
		}
	}
	cout<<s[n]<<"\n";
}