数列游戏


第二题 数列游戏
提交文件: sequence.cpp
输入文件: sequence.in
输出文件: sequence.out
时间空间限制: 1 秒, 256 MB
有一个长度为 \(n\) 的序列 \(a_1, \cdots , a_n\)
如果序列的长度大于 1,那么你就能进行操作,每次操作可以选择两个相邻的数 \(a_i\), \(a_{i+1}\) 合并,得到一个新的数 \(ai ⊕ a_{i+1}\)(“\(⊕\)”表示异或),每次操作都会使序列的长度减少 1。例如对将序列 \([8, 3, 5, 7, 1]\) 中的第 2个和第 3 个数进行合并,会得到新序列 \([8, 6, 7, 1]\),并可以进行下一轮操作。
你需要进行若干次操作(可能是 \(0\) 次),使得最终序列任意子区间的异或和不为 0。子区间的定义为连续的一段数 \([a_l, a_{l+1},\cdots , a_r](l ≤ r)\)。求满足条件的最终序列的最长长度。
输入格式
第一行一个正整数 \(n\),表示序列长度。
第二行 \(n\) 个正整数 \(a_1,\cdots , a_n\),表示序列。
输出格式
一个整数,满足条件的最终序列的最长长度。如果不存在这样的序列则输出“-1”(不含引号)。
样例数据

4
5 5 7 2
2

样例解释
一种方案是先选择 \(a_1, a_2\) 合并,得到 \([0, 7, 2]\),再选择前两个数合并,得到 \([7, 2]\)。不存在方案使得最终序
列长度为 \(3\)\(4\)
数据范围
对于所有测试点,\(1 ≤ n ≤ 10^5,0 ≤ a_i ≤ 10^9\)

测试点 $n ≤ $ \(a_i ≤\)
1 ~ 4 15 \(10^9\)
5 ~ 8 100 3
9 ~ 12 1000 3
13 ~ 16 \(10^5\) 3
17 ~ 20 \(10^5\) \(10^9\)

首先考虑前缀异或和,合并两个数,相当于去掉一个数。那么问题就是在前缀异或和中,每次删除一个1~n-1的数,问要多少次使得前缀异或和中没有相同的数。
设前缀异或和为\(s\),那么如果\(s_n=0\),整个数列的异或和始终为0,无解。
否则,如果出现两个相同的,那就要删除一个即可。也就是拿map判断重复,出现重复答案就加1.

#include 
using namespace std;
const int N=1e5+5;
int n,a[N],s[N],cnt;
mapmp;
int main()
{
//	freopen("sequence.in","r",stdin);
//	freopen("sequence.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",a+i),s[i]=s[i-1]^a[i];
	if(!s[n])
	{
		printf("-1");
		return 0;
	}
	for(int i=0;i<=n;i++) 
	{
		if(mp[s[i]])
			++cnt;
		mp[s[i]]=1;
	}
	printf("%d",n-cnt);
	return 0;
}