Sum of XOR Functions
题目
有一个序列 \(a\),计算:
\[\sum\limits_{l=1}^{n}\sum\limits_{r=l}^n(r-l+1)\times \bigoplus\limits_{i=l}^{r}a_i \]思路
位运算的题,我们对于每一位进行考虑,会发现构成了很多个 \(0,1\) 序列,则我们对于每一个序列考虑价值,求和即可。
设 \(b\) 序列为这一位上的 \(0,1\) 序列。
对于 \(0,1\) 序列的一段区间的异或和,只有在这段区间中 \(1\) 的数量为奇数个时才为 \(1\)。
我们用 \(cnt_{i,0/1}\) 表示这一位的零一序列中第 \(i\) 个位置前 \(0/1\) 出现的个数。
用 \(sum_{i,0/1}\) 表示:
\[\sum^{x}_{\{\bigoplus^{i}_{k = x}b_k\} = 0/1}(i - x) \]也就是说,表示对于 \(i\) 位置前所有能满足使 \(\{ \bigoplus^{i}_{k = x} b_k \} = 1\) 的位置 \(x\) 到位置 \(i\) 的距离和。
我们发现当我们预处理完成这些数组时,就可以 \(O(1)\) 求出:\(\sum^{i}_{x = 1} \{\bigoplus^{i}_{k = x} b_k\}\) 的值了。
接下来就是 \(O(n)\) 的复杂度枚举右端点的值即可。
主要思路到此结束。
\(code\)
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
#define int long long
const int MOD = 998244353;
const int MAXN = 3e5 + 7;
int n,a[MAXN];
int cnt[MAXN][2],sum[MAXN][2];
int pre[MAXN];
int ans = 0;
signed main(){
scanf("%lld", &n);
for(int i = 1;i <= n;i++) scanf("%lld", &a[i]);
for(int w = 0;w <= 31;w++){
memset(cnt,0,sizeof(cnt));
memset(sum,0,sizeof(sum));
memset(pre,0,sizeof(pre));
cnt[0][0] = 1;
for(int i = 1;i <= n;i++){
pre[i] = pre[i - 1];
cnt[i][0] = cnt[i - 1][0];
cnt[i][1] = cnt[i - 1][1];
sum[i][0] = sum[i - 1][0];
sum[i][1] = sum[i - 1][1];
pre[i] += (a[i] >> w) & 1;
if(pre[i] & 1) cnt[i][1]++,sum[i][1] += i;
else cnt[i][0]++,sum[i][0] += i;
}
for(int i = 1;i <= n;i++){
if(pre[i] & 1) ans = (ans + ((cnt[i - 1][0] * i - sum[i - 1][0]) % MOD) * (1 << w) % MOD) % MOD;
else ans = (ans + ((cnt[i - 1][1] * i - sum[i - 1][1]) % MOD) * (1 << w) % MOD) % MOD;
ans = ans % MOD;
}
}
cout<<ans;
return 0;
}
标签:Functions,XOR,int,Sum,cnt,MAXN,bigoplus,序列,sum
From: https://www.cnblogs.com/wyl123ly/p/18436384