子数组异或和
子数组异或和
给定一个长度为 的整数数组 。
请你统计一共有多少个数组 的非空连续子数组能够同时满足以下所有条件:
- 该连续子数组的长度为偶数。
- 该连续子数组的前一半元素的异或和等于其后一半元素的异或和。
例如,当给定数组为 时,满足条件的连续子数组只有 个:。
输入格式
第一行包含整数 。
第二行包含 个整数 。
输出格式
一个整数,表示满足条件的连续子数组的数量。
数据范围
前三个测试点满足 。
所有测试点满足 。
输入样例1:
5 1 2 3 4 5
输出样例1:
1
输入样例2:
6 3 2 2 3 7 6
输出样例2:
3
输入样例3:
3 42 4 2
输出样例3:
0
解题思路
这题昨天想了很久都没想出来怎么做,想到了用异或前缀和,但没发现题目第二个隐含的性质,现在做题的抽象能力十分差,很难把一个问题抽象成学过的模型。
假设有异或和,根据同一个数的异或和为这个性质,那么有
对于第二个条件,假设子数组前一半的异或和为,后一半的异或和为,那么就有,因此有。
因此可以枚举子区间的右端点,找到左端点,满足区间长度为偶数,同时满足,即。因此我们要在中找到有多少个满足,同时为为偶数,即满足和的奇偶性相同。因此可以开两个哈希表,分别统计为奇偶时的。
AC代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int N = 1 << 20; 5 6 int cnt[2][N]; // 因为ai<2^20,因此异或和不超过2^20 7 8 int main() { 9 int n; 10 scanf("%d", &n); 11 12 long long ret = 0; 13 cnt[0][0] = 1; 14 for (int i = 1, sum = 0; i <= n; i++) { 15 int v; 16 scanf("%d", &v); 17 sum ^= v; 18 ret += cnt[i & 1][sum]; 19 cnt[i & 1][sum]++; 20 } 21 22 printf("%lld", ret); 23 24 return 0; 25 }
参考资料
AcWing 4507. 子数组异或和(AcWing杯 - 周赛):https://www.acwing.com/video/4213/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/16586364.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效