ABC365E Xor Sigma Problem 题解

ABC365E Xor Sigma Problem 题解

题目大意

给定长度为 \(n\) 的序列 \(A\),求 \(\displaystyle \sum_{i=1}^{N-1}\sum_{j=i+1}^N (A_i \oplus A_{i+1}\oplus \ldots \oplus A_j)\)

Solve

看到异或不难想到按位枚举,按位枚举时维护什么信息呢?

考虑对于序列 \(A\),我们倒序枚举,那么在加入 \(A_i\) 之前得到的区间异或和之和形如:

\[(A_{i+1}\oplus A_{i+2}\oplus \dots\oplus A_n)+(A_{i+1}\oplus A_{i+2}\oplus \dots\oplus A_{n-1})+\dots+(A_{i+1}\oplus A_{i+2}) \]

加入 \(A_i\) 后,这个表达式的每个括号里都要异或上 \(A_i\)。那么从结果上看,若 \(A_i\) 的第 \(j\) 位是 \(1\),则异或和的第 \(j\) 位就要反转。

故我们考虑维护如下信息:对于第 \(i\) 位,\(cnt_{i,1}\) 表示有多少段异或和(上式中每一个括号内的值)这一位是 \(1\)\(cnt_{i,0}\) 表示有多少段异或和这一位是 \(0\)。统计答案时直接加上 \(2^i\times cnt_{i,1}\) 即可。

加入 \(A_i\) 后,按位扫一遍,如果 \(A_i\)\(j\) 位是 \(1\),就交换 \(cnt_{j,0}\)\(cnt_{j,1}\)。同时别忘了,加入 \(A_{i-1}\) 时多了一段 \(A_{i-1}\oplus A_i\),故我们还要让 \(cnt_{j,A_{i,j}}\) 加上 \(1\) 方便后面统计答案。

Code

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read()
{
	short f=1;
	int x=0;
	char c=getchar();
	while(c<'0'||c>'9')	{if(c=='-')	f=-1;c=getchar();}
	while(c>='0'&&c<='9')	x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
const int N=2e5+10;
int n,a[N],ans,cnt[35][2];
signed main()
{
	n=read();
	for(int i=1;i<=n;i=-~i)	a[i]=read();
	for(int i=n;i;i--)
	{
		for(int j=30;j>=0;j--)
			ans+=cnt[j][(a[i]>>j&1)^1]*(1<<j);
		for(int j=30;j>=0;j--)
		{
			if(a[i]>>j&1)	swap(cnt[j][1],cnt[j][0]);
			cnt[j][a[i]>>j&1]++;
		}
	}
	return printf("%lld",ans),0;
}
posted @   Sorato  阅读(99)  评论(0编辑  收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示