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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步