[模板]线性基

用途

处理关于子集的异或和的问题,比如子集异或和的最大值,或者能不能异或出某个数

原理

从一堆数中处理出一组线性无关(?)的数,使得这些数能异或出的数和原来能异或出的数相同

线性基中,以每个位置为最高位1的数(最多)只有一个,这样就保证了线性无关

做法

依次处理每个数,对于x,从大到小扫描它的每一位,当扫到第i位为1时:

  若线性基中没有最高位为i的数,则把x插到线性基中,结束扫描

  若有,则把x异或上那个数,继续做

这样做,如果一个数最终没有被插入线性基中,证明它已经能被线性基中的数表示

而插到线性基中的数,也一定是几个原数的异或和

最后我如果想找能异或出的最大的数,那就从高到低扫线性基中的每个数,如果异或上能使答案变大,就异或上,毕竟机不可失时不再来

例题

luogu3812

 1 #include<bits/stdc++.h>
 2 #define CLR(a,x) memset(a,x,sizeof(a))
 3 #define MP make_pair
 4 using namespace std;
 5 typedef long long ll;
 6 typedef unsigned long long ull;
 7 typedef pair<int,int> pa;
 8 const int maxn=55;
 9
10 inline ll rd(){
11     ll x=0;char c=getchar();int neg=1;
12     while(c<‘0‘||c>‘9‘){if(c==‘-‘) neg=-1;c=getchar();}
13     while(c>=‘0‘&&c<=‘9‘) x=x*10+c-‘0‘,c=getchar();
14     return x*neg;
15 }
16
17 int N;
18 ll a[maxn],x[maxn];
19
20 int main(){
21     //freopen("","r",stdin);
22     int i,j,k;
23     N=rd();
24     for(i=1;i<=N;i++) a[i]=rd();
25     for(i=1;i<=N;i++){
26         for(j=50;j>=0;j--){
27             if(a[i]&(1ll<<j)){
28                 if(!x[j]){
29                     x[j]=a[i];break;
30                 }else a[i]^=x[j];
31             }
32         }
33     }
34     ll ans=0;
35     for(i=50;i>=0;i--){
36         if((ans^x[i])>ans) ans^=x[i];
37     }
38     printf("%lld\n",ans);
39     return 0;
40 }

如果您像我一样容易忘记写break的话,可以考虑不写else,反正如果我这次插进去了,再异或上我自己就变成了0,就相当于break了

原文地址:https://www.cnblogs.com/Ressed/p/10066528.html

时间: 2024-10-05 09:19:27

[模板]线性基的相关文章

[P3812][模板]线性基

解题关键:求异或最大值.线性基模板题. 极大线性无关组的概念. 异或的值域相同. #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<iostream> #include<cmath> using namespace std; typedef long long ll; const int MAX_BASE=63; ll b

[算法模板]线性基

线性基 GavinZheng敲懒的... menci大佬的线性基博客 模板代码引自menci: struct LinearBasis { long long a[MAXL + 1]; LinearBasis() { std::fill(a, a + MAXL + 1, 0); } LinearBasis(long long *x, int n) { build(x, n); } void insert(long long t) { for (int j = MAXL; j >= 0; j--)

[洛谷3812]【模板】线性基

题目大意: 给你n个数,求这些数能异或出的数的最大值. 思路: 线性基模板. b中的数满足对于每个b[i],最高位在第i位. 构造方法就是对于每个数字,从高到低枚举每一个1,如果这一位对应的b[i]还没有,就把这个数作为b[i],如果有,就把这个数异或上b[i]. 考虑两个数a,b,它们能异或出来的数为0,a,b,a xor b,如果把b换成a xor b,它们能异或出来的数还是0,a,b,a xor b. 所以b能异或出来的值域和a能异或出来的值域相同. 最后能异或出的最大值可以用类似贪心的思

【模板】线性基

线性基就是一种可以维护异或和的东西,我还没太懂它到底有什么用,但是很好写,而且思路也很清晰,所以板子还是很简单的. 题干: 题目背景 这是一道模板题. 题目描述 给定n个整数(数字可能重复),求在这些数中选取任意个,使得他们的异或和最大. 输入输出格式 输入格式: 第一行一个数n,表示元素个数 接下来一行n个数 输出格式: 仅一行,表示答案. 输入输出样例 输入样例#1: 复制 2 1 1 输出样例#1: 复制 1 说明 1≤n≤50,0≤Si≤250 1 \leq n \leq 50, 0 \

P3812 【模板】线性基

P3812 [模板]线性基 理解 :线性基 类似于 向量的极大无关组,就是保持原来所有数的异或值的最小集合, 求解过程也类似,可以 O( 60 * n )的复杂度求出线性基,线性基有许多性质,例如 线性基 里面的数进行异或 的值域与原来所有数异或的值域相同. #include<bits/stdc++.h> using namespace std; #define ll long long #define maxn 123 ll n,a[maxn],ans,p[maxn]; void getji

HDU3949 线性基模板

Ac链接 给定n个数,求子集异或和的第k大.\(n\le10^5,a_i\le10^9\). 第一步肯定是构造线性基.设线性基的基底数量为k,那么子集异或和本质不同的个数为\(2^k\)(如果有为0的情况).其实求第k大很简单,你把k拆分成2进制,对应基底从左到右的每一位,如果为1就异或上去就行了.不过我们需要分为两种情况,一个是存在异或和为0的情况,一个是不存在的.如果不存在异或和为0,需要把k+1. #include<bits/stdc++.h> #define ll long long

线性基(模板)

这里是连接o(´^`)o 线性基性质: 1.原序列里面的任意一个数都可以由线性基里面的一些数异或得到.2.线性基里面的任意一些数异或起来都不能得到0 03.线性基里面的数的个数唯一,并且在保持性质一的前提下,数的个数是最少的 //#include<bits/stdc++.h> #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cs

线性基总结(其实就是我的模板)

想知道线性基直接看大佬的https://blog.sengxian.com/algorithms/linear-basis, 我就是弄下我常用的操作. 定义 学过线代里面的“基向量”,基向量说的就是一组可以表示整个空间的向量.比如在三维空间中一个基向量就是(1,0,0) (0,1,0) (0,0,1).线性基的定义也类似,给你一个数组a[ ],它的线性基就是一组可以表示数组a中任意一个数的一个数组p[ ].这个表示的意思就和前面的基向量表示的意思类似,是通过p中几个元素的异或得到a中的任意一个元

LG3812 「模板」线性基 线性基

问题描述 LG3812 题解 线性基是一类擅长解决异或问题的数据结构(也不算数据结构吧...就是一种玄学的东西) 对于数列 \(a\) ,它的线性基 \(d\) 为 出现 \(1\) 的最高位在第 \(i\) 位的数 (这里借用了"帅到报警"的题解). 构造方法 对于每一个尝试插入的数 \(x\) ,找出它目前为 \(1\) 的最高位 \(pos\) . 如果这个时候 \(d_pos\) 已经有了一个数,那么就把 \(x\) 异或上 \(d_pos\) 继续尝试. 否则插入,插入成功后