【线性基】Codeforces-1101G. (Zero XOR Subset)-less

题目链接

time limit per test 2 seconds

memory limit per test 256 megabytes

input standard input

output standard output

Description

You are given an array a1,a2,,an of integer numbers.

Your task is to divide the array into the maximum number of segments in such a way that:

  • each element is contained in exactly one segment;
  • each segment contains at least one element;
  • there doesn't exist a non-empty subset of segments such that bitwise XOR of the numbers from them is equal to 0.

Print the maximum number of segments the array can be divided into. Print 1 if no suitable division exists.

Input

The first line contains a single integer n(1n2105) — the size of the array.

The second line contains nn integersa1,a2,,an(0ai109).

Output

Print the maximum number of segments the array can be divided into while following the given constraints. Print 1 if no suitable division exists.

Examples

input
4
5 5 7 2
output
2
input
3
1 2 3
output
-1
input
3
3 1 10
output
3
Note

In the first example 2 is the maximum number. If you divide the array into{[5],[5,7,2]}, the XOR value of the subset of only the second segment is 572=0,{[5,5],[7,2]} has the value of the subset of only the first segment being 55=0. However, {[5,5,7],[2]} will lead to subsets {[5,5,7]} of XOR 7, {[2]} of XOR 2 and {[5,5,7],[2]} of XOR 5572=5.

Let's take a look at some division on 3 segments — {[5],[5,7],[2]}. It will produce subsets:

  • {[5]}, XOR 5;
  • {[5,7]}, XOR 2;
  • {[5],[5,7]}, XOR 7;
  • {[2]}, XOR 2;
  • {[5],[2]}, XOR 7;
  • {[5,7],[2]}, XOR 0;
  • {[5],[5,7],[2]}, XOR 5;

As you can see, subset {[5,7],[2]} has its XOR equal to 0, which is unacceptable. You can check that for other divisions of size 3 or 4, non-empty subset with 00 XOR always exists.

The second example has no suitable divisions.

The third example array can be divided into {[3],[1],[10]}. No subset of these segments has its XOR equal to 0.

题意

给出一个长度为n的序列{ai},试将其划分为尽可能多的非空子段,满足

每一个元素出现且仅出现在其中一个子段中,每个段至少包含一个元素,不存在段组成的非空子集使得这些段的数的异或和为0n(1n2105),ai(0ai109)

思路

把这个数组分段为 (a1...ax1)(ax1+1...ax2)...(...an)

每个段都有一个异或值,每一段异或起来又可以看成是它的两个前缀异或和的异或值

即第一段S(x1)^S(0) ,第二段S(x2)^S(x1)...

又有要求:不存在段组成的非空子集使得这些段的数的异或和为0

S(0)~S(n)里面取偶数个异或出来的值不能为0,也就意味着取出来的数必然是线性无关的,实际上就是求一个极大线性无关组,做前缀和的线性基。

这个线性基的大小就是最多的段数。

有一个特殊情况,S(n)=0时,不管怎么做都不可能取到满足条件的段,所有的异或起来就会是0

AC代码

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define inf 0x3f3f3f3f
#define PII pair<int,int>
#define endl '\n'
const int N = 2e5 + 10;
const int mod = 1e9 + 7;
const double pi = acos(-1.0);
typedef long long ll;
int t, n, m;
int arr[N], base[65];//最高位为第i位的基
int ans;
void insert(int x) {
	for (int i = 60; i >= 0; i--) {
		if (!(x >> i)) {
			continue;
		}
		if (base[i] == 0) {
			base[i] = x;
			break;
		}
		else x ^= base[i];
	}
	if (x) ans++;
	return;
}
void init() {
	for (int i = 0; i <= 64; i++) {
		base[i] = 0;
	}
	for (int i = 0; i <= n; i++) {
		arr[i] = 0;
	}
	ans = 0;
	return;
}
void solve() {
	init();
	cin >> arr[1];
	insert(arr[1]);
	int spj = arr[1];
	for (int i = 2; i <= n; i++) {
		cin >> arr[i];
		spj ^= arr[i];
		insert(arr[i]);
	}
	if (spj == 0) cout << -1 << endl;
	else cout << ans << endl;
	return;
}
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	while (cin >> n) {
		solve();
	}
	return 0;
}
posted @   TomiokapEace  阅读(56)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
点击右上角即可分享
微信分享提示