线性基初探

关于线性基的学习与理解

1、线性基:

  若干数的线性基是一组数\(a_1,a_2,...a_n\)其中\(a_x\)的最高位的1在第x位。
  
  通过线性基中元素\(xor\)出的数的值域与原来的数\(xor\)出数的值域相同。

2、线性基的构造法:

  对每一个数\(p\)从高位到低位扫,扫到第\(x\)位为1时,若\(a_x\)不存在,则\(a_x=p\)并结束此数的扫描,否则令\(p=pxora_x\)。

3、查询:

  用线性基求这组数\(xor\)出的最大值:从高往低扫\(a_x\),若异或上\(a_x\)使答案变大,则异或。

4、判断:

  用线性基求一个数能否被\(xor\)出:从高到低,对该数每个是1的位置x,将这个数异或上\(a_x\)(注意异或后这个数为1的位置和原数就不一样了),若最终变为0,则可被异或出。当然需要特判0(在构造过程中看是否有p变为0即可)。
个人谈一谈对线性基的理解:
  很多情况下,只有有关异或运算和求最值,就可以用到线性基。线性基有很多很好的性质,比如说
  如果有很多个数,我们可以构出这些数的线性基,那么这个线性基可以通过互相\(xor\),能够构出原来的数可以相互\(xor\)x构出的所有的数。所以可以大大减少判断的时间和次数。
  同时线性基的任何一个非空子集都不会使得其\(xor\)和为0,证明也很简单,反证法就可以说明。
  这个性质在很多题目中可以保证算法合法性,比如:[BJWC2011]元素(按权值从大到小插入到线性基中就可以保证得到的线性基中的元素是权值之和最大的。)。
构造的方法有点像贪心,从大到小保证高位更大。也比较好理解。就是这几行代码:

for(re i=1;i<=n;++i)
    for(re j=62;j>=0;--j)
        if(a[i]&(1ll<<j)){
            if(!p[j]){p[j]=a[i];break;}
            else a[i]^=p[j];
        }

  可以把\(n\)个数变成只有最大的数的二进制位数那么多个数,这就是线性基的优秀之处。
查询的话,也是一个贪心思想,如果可以使得\(ans\)更大,就把这一位的基\(xor\)进\(ans\)。

for(int i=62;i>=0;i--) if((ans^p[i])>ans) ans=ans^p[i];
//从线性基中得到最大值 

  这就是线性基的基本用法和个人的一些理解。

原文地址:https://www.cnblogs.com/Sparks-Pion/p/9709626.html

时间: 2024-07-30 12:54:52

线性基初探的相关文章

Xor HYSBZ - 2115 (线性基)

Xor HYSBZ - 2115 题意:给一个树,求1到n的最长路径.这里的路径定义为异或和. 线性基~~ 1 #include <bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 struct LiBase{ 5 ll a[63]; 6 //初始化 7 void init(){ 8 memset(a,0,sizeof(a)); 9 } 10 //插入 11 bool insert_(ll x){ 12 for(int

线性基小节

1.线性基的异或集合中每个元素的异或方案唯一. 2.线性基二进制最高位互不相同. 3.线性基中元素互相异或,异或集合不变. 摘自百度文库 线性基能相互异或得到原集合的所有相互异或得到的值. 线性基是满足性质1的最小的集合 线性基没有异或和为0的子集. 证明: 反证法:设线性基S={a1,a2...,an}: 若有子集a1^a2^...^at=0,则a1=a2^a3^...^at,则舍弃a1后一定能通过剩余的元素异或出所有需要a1参与异或的值.设Y=a1^X,因为{a1,a2,...,an}是一组

[BeiJing2011]元素[贪心+线性基]

2460: [BeiJing2011]元素 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1245  Solved: 652[Submit][Status][Discuss] Description 相传,在远古时期,位于西方大陆的 Magic Land 上,人们已经掌握了用魔法矿石炼制法杖的技术.那时人们就认识到,一个法杖的法力取决于使用的矿石.一般地,矿石越多则法力越强,但物极必反:有时,人们为了获取更强的法力而使用了很多矿石,却在炼制过程中

BZOJ 3105: [cqoi2013]新Nim游戏 [高斯消元XOR 线性基]

以后我也要用传送门! 题意:一些数,选择一个权值最大的异或和不为0的集合 终于有点明白线性基是什么了...等会再整理 求一个权值最大的线性无关子集 线性无关子集满足拟阵的性质,贪心选择权值最大的,用高斯消元判断是否和已选择的线性相关 每一位记录pivot[i]为i用到的行 枚举要加入的数字的每一个二进制为1的位,如果有pivot[i]那么就异或一下(消元),否则pivot[i]=这个数并退出 如果最后异或成0了就说明线性相关... #include <iostream> #include &l

【BZOJ2844】albus就是要第一个出场 线性基 高斯消元

#include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/43456773"); } 题意:需要注意的是空集(0)是天生被包括的,我为了这个WA了好久~拍了好久,醉了好久~ 题解: 首先有一个我并不知道是为什么(甚至不知道它对不对)的性质: 每一种权值会出现2的自由元(n-线性基个数)次方 次. 感性

[bzoj 2460]线性基+贪心

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2460 网上很多题目都没说这个题目的证明,只说了贪心策略,我比较愚钝,在大神眼里的显然的策略还是想证明一下才安心--所以这里记录一下证明过程. 贪心策略:按魔力值从大到小排序,从大往小往线性基里插,如果成功插入新元素,就选这个,如果插不进去,就不选这个. 证明: 设有n个材料,每个材料的属性值是x[1],x[2],...,x[n],魔力值是v[1],v[2],...,v[n],这里假设v已

BZOJ 2460 元素(贪心+线性基)

显然线性基可以满足题目中给出的条件.关键是如何使得魔力最大. 贪心策略是按魔力排序,将编号依次加入线性基,一个数如果和之前的一些数异或和为0就跳过他. 因为如果要把这个数放进去,那就要把之前的某个数拿出来,而这样交换之后集合能异或出的数是不会变的,和却变小了. # include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include <vector

线性基 学习笔记

ps:做CF的时候碰到了一个线性基的概念,然后在网上学习了一下,发现相关的资料很少,所以打算来写一个我个人的理解. 线性代数中 有极大线性无关组和空间的基的概念.  线性基的性质与此类似. 首先来看一个问题: 给出N个数,要从中选出一个最大的子集,使得子集中的任意个元素异或值不为0. 这个和极大线性无关组有些类似.异或可以看出是模2域下的加法运算,如果把一个数转化为二进制,对应成一个由01构成的向量, 所有这些向量就构成了一个线性空间. 原问题就转化为求这个向量组的极大线性无关组,把这样一个极大

【线性基】hdu3949 XOR

给你n个数,问你将它们取任意多个异或起来以后,所能得到的第K小值? 求出线性基来以后,化成简化线性基,然后把K二进制拆分,第i位是1就取上第i小的简化线性基即可.注意:倘若原本的n个数两两线性无关,也即线性基的大小恰好为n时,异或不出零,否则能异或出零,要让K减去1. 这也是线性基的模板. #include<cstdio> #include<cstring> using namespace std; typedef long long ll; ll d[64],p[64]; int