CF1879D Sum of XOR Functions
异或和按位处理的典型例题。要求所有子区间异或和乘区间长度的总和,朴素的方法是
因为涉及异或和,而异或运算不进位,故自然地想到把
1. 二进制拆分
比方说,对于如下样例,我们把
a[1] = 5 = 0101
a[2] = 11 = 1011
a[3] = 7 = 0111
a[4] = 4 = 0100
第 1110
,第 0110
……
2. 对每一位求贡献
二进制拆分后,问题也就转化成了:对每个 01 串求所有含有奇数个
下面用 dp 求
要研究区间,往往通过前缀来转化。有哪些情况能使得区间
- 如果区间
有奇数个 ,区间 有偶数个 ,则区间 有奇数个 ; - 如果区间
有偶数个 ,区间 有奇数个 ,则区间 有奇数个 。
由此,我们
- 设
表示在 中,有多少个前缀含有偶数/奇数个 ; - 设
表示在 中,含有偶数/奇数个 的前缀总长度是多少; - 设
表示恰好以 结尾的含有奇数个 的区间的总长度,显然 。
于是有
这实质上是把所有前缀和作差求区间和的操作放在一起做。
3. 合并每一位统计答案
最终的答案
void solve() {
int n, ans = 0;
cin >> n;
vector<int> a(n + 1), b(n + 1);
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int t = 0; t <= 30; t++) {
for (int i = 1; i <= n; i++) {
b[i] = (a[i] >> t) & 1;
}
int x = 0, res = 0; // the number of 1s
int cnt[2] = {1, 0}; // the number of the intervals
int sum[2] = {0, 0}; // the sum of the intervals' lengthes
for (int i = 1; i <= n; i++) {
x = (x + b[i]) % 2;
res = (res + (LL)cnt[1 - x] * i % mod - sum[1 - x] + mod) % mod;
cnt[x]++, sum[x] = (sum[x] + i) % mod;
}
ans = (ans + (LL)res * ((1 << t) % mod) % mod) % mod;
}
cout << ans << endl;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!