「线性基」学习笔记and乱口胡总结

还以为是什么非常高大上的东西花了1h不到就学好了

线性基

线性基可以在 O ( n l o g x ) O(nlogx) O(nlogx)的时间内计算出 n n n个数的最大异或和(不需要相邻)。
上述中 x x x表示的最大的数。

如何实现

定义 p [ i ] p[i] p[i]表示在二进制下从最高位开始第一个出现 1 1 1的数。
当前我们将一个数插入线性基中。
如果 x x x的最高位的 1 1 1还没有被插入过,那么就在这一位上插入 x x x
如果没有被插入过,那么就异或上这一位上的数。
查询操作:从最高位上开始贪心。
如果异或这一位上的数可以让答案更大,那么就异或,否则就异或。

贪心验证

因为我们从高位往低位贪心,所以不需要考虑低位上的数会让高位上的数变小的情况。
介于我们在插入的时候都是无法匹配的时候,异或上这一位上的数,那么就保证了我们的这个数能够达到自己能用的最大贡献。

代码

【洛谷模板区】

#include <bits/stdc++.h>
using namespace std;
const int BIT = 63;
const int N = 52;
typedef long long ll;
ll a[N], p[BIT + 2];
int n; 
void ins(ll x) {
	for (int i = BIT; ~i; i --) {
		if ((x >> i) == 0) continue; 
		if (!p[i]) { p[i] = x; break; }
		x ^= p[i];
	}
}
int main() {
	cin >> n;
	for (int i = 1; i <= n; i ++) cin >> a[i];
	for (int i = 1; i <= n; i ++) ins(a[i]);
	for (int i = 0; i <= BIT; i ++) cout << i << " " << p[i] << endl; cout << endl;
	ll ans = 0;
	for (int i = BIT; ~i; i --) 
		if ((ans ^ p[i]) > ans) ans ^= p[i];
	cout << ans << endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值