Problem - 1109A - Codeforces
Sasha喜欢编程。有一次,在一场很长时间的比赛中,萨沙觉得他有点累了,需要放松一下。他照做了。但由于萨沙不是一个普通人,他更喜欢不同寻常地放松。在闲暇时间,萨沙喜欢解决未解决的问题,因为解决问题非常有用。
因此,Sasha决定解决以下问题:
你有一个包含n个整数的数组a。你需要计算有趣的组合(l,r)的个数(l≤r)。为了检验一对(l,r)是否具有好笑性,取mid=l+r−12,那么如果r−l+1是偶数且al⊕al+1⊕…⊕amid=amid+1⊕amid+2⊕…⊕ar,那么这对组合就是好笑的。换句话说,子数组左半部分元素从l到r的⊕应该等于右半部分元素的⊕。请注意⊕表示按位异或运算。
是时候继续解决比赛了,Sasha让你解决这个任务。
输入
第一行包含一个整数n(2≤n≤3⋅105)——数组的大小。
第二行包含n个整数a1,a2,…,an(0≤ai<220) -数组本身。
输出
打印一个整数——有趣的数字对的个数。你应该只考虑r−l+1为偶数的对偶。
例子
inputCopy
5
1 2 3 4 5
outputCopy
1
inputCopy
6
3 2 2 3 7 6
outputCopy
3.
inputCopy
3.
42 42
outputCopy
0
请注意
像萨沙一样冷静,解决问题!
在第一个例子中,唯一有趣的一对是(2,5),因为2⊕3=4⊕5=1。
在第二个例子中,有趣的组合是(2,3)、(1,4)和(3,6)。
在第三个例子中,没有有趣的配对。
题解:
根题意要我们让一个偶数区间的一半异或结果等于另外一半,
设mid = (l + r - 1)
根据前缀和的性质和异或的性质
al^al+1...^amid = s[mid]^s[l-1]
amid+1^....ar = s[r]^s[mid]
所以s[r] == s[l-1]
接下来我们只需要记录下标为偶数或奇数时,前缀出现次数即可,
#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<vector>
#include<map>
#include<cstring>
#include<cmath>
#include<stack>
#include<set>
using namespace std;
#define int long long
typedef pair<int,int> PII;
const int N = 2e5 + 10;
int a[2][2000050];
void solve()
{
int n;
cin >> n;
a[0][0] = 1;
int y = 0;
int ans = 0;
for(int i = 1;i <= n;i++)
{
int x;
cin >> x;
y ^= x;
ans += a[i%2][y];
a[i%2][y]++;
}
cout << ans;
}
//1 -7 1 -7
signed main(){
// ios::sync_with_stdio(false);
// cin.tie(0);
// cout.tie(0);
int t = 1;
// cin >> t;
while(t--)
{
solve();
}
}
//3 3 2 2 1 0
//1 2 1 1 1 0