ABC365E Xor Sigma Problem 題解

Sorato發表於2024-08-07

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;
}

相關文章