线性基(一

1、线性基:

  若干数的线性基是一组数a1,a2,...ana1,a2,...an,其中axax的最高位的11在第xx位。

  通过线性基中元素xorxor出的数的值域与原来的数xorxor出数的值域相同。

2、线性基的构造法:

  对每一个数pp从高位到低位扫,扫到第xx位为11时,若axax不存在,则ax=pax=p并结束此数的扫描,否则令p=pp=p   xorxor ax。ax。

3、查询:

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

4、判断:

  用线性基求一个数能否被xorxor出:从高到低,对该数每个是11的位置xx,将这个数异或上axax(注意异或后这个数为1的位置和原数就不一样了),若最终变为00,则可被异或出。当然需要特判00(在构造过程中看是否有p变为0即可)。例子:(11111,10001)(11111,10001)的线性基是a5=11111a5=11111,a4=01110a4=01110,要判断1111111111能否被xorxor出,1111111111 xorxor a5a5=0=0,则这个数后来就没有是11的位置了,最终得到结果为00,说明1111111111能被xorxor出。

个人谈一谈对线性基的理解:

  很多情况下,只有有关异或运算和求最值,就可以用到线性基。线性基有很多很好的性质,比如说如果有很多个数,我们可以构出这些数的线性基,那么这个线性基可以通过互相xorxor,能够构出原来的数可以相互xorxor构出的所有的数。所以可以大大减少判断的时间和次数。同时线性基的任何一个非空子集都不会使得其xorxor和为0,证明也很简单,反证法就可以说明。这个性质在很多题目中可以保证算法合法性,比如:BZOJ2460BZOJ2460。

  构造的方法有点像贪心,从大到小保证高位更大。也比较好理解。就是这几行代码:

  


1

2

3

4

5

6

7

8

9

10

11

12

13

for(int i=1;i<=n;i++) {    

        for(int j=62;j>=0;j--) {

             if(!(a[i]>>j)) continue;//对线性基的这一位没有贡献           

               if(!p[j]) { p[j]=a[i]; break; }//选入线性基中                   

               a[i]^=p[j];

             }

       }

  

  可以把nn个数变成只有最大的数的二进制位数那么多个数,这就是线性基的优秀之处。

  查询的话,也是一个贪心思想,如果可以使得ansans更大,就把这一位的基xorxor进ansans。

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

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

下面看一些练习(例题):

1、BZOJ2460

Description

相传,在远古时期,位于西方大陆的 Magic Land 上,人们已经掌握了用魔法矿石炼制法杖的技术。那时人们就认识到,一个法杖的法力取决于使用的矿石。
一般地,矿石越多则法力越强,但物极必反:有时,人们为了获取更强的法力而使用了很多矿石,却在炼制过程中发现魔法矿石全部消失了,从而无法炼制出法杖,这个现象被称为“魔法抵消” 。特别地,如果在炼制过程中使用超过一块同一种矿石,那么一定会发生“魔法抵消”。 
后来,随着人们认知水平的提高,这个现象得到了很好的解释。经过了大量的实验后,著名法师 Dmitri 发现:如果给现在发现的每一种矿石进行合理的编号(编号为正整数,称为该矿石的元素序号),那么,一个矿石组合会产生“魔法抵消”当且仅当存在一个非空子集,那些矿石的元素序号按位异或起来为零。 (如果你不清楚什么是异或,请参见下一页的名词解释。 )例如,使用两个同样的矿石必将发生“魔法抵消”,因为这两种矿石的元素序号相同,异或起来为零。 
 并且人们有了测定魔力的有效途径,已经知道了:合成出来的法杖的魔力等于每一种矿石的法力之和。人们已经测定了现今发现的所有矿石的法力值,并且通过实验推算出每一种矿石的元素序号。 
现在,给定你以上的矿石信息,请你来计算一下当时可以炼制出的法杖最多有多大的魔力。

正解:贪心+线性基

解题报告:

  显然这道题可以用线性基来维护一个我们选取的非空子集中不存在异或出00的情况,但是我们还需要得到的权值最大,那么直接对于每件物品按权值排序,按权值从大到小插入到线性基中就可以保证得到的线性基中的元素是权值之和最大的。

2、BZOJ2115

Description

正解:线性基

解题报告:

  这道题要求从1到n的最大xor和路径,存在重边,允许经过重复点、重复边。那么 在图上作图尝试之后就会发现,路径一定是由许多的环和一条从1到n的路径组成。容易发现,来回走是没有任何意义的,因为来回走意味着抵消。考虑这道题求得是路径xor和最大,所以必然我们要想办法处理环的情况。我的做法是任意地先找出一条从1到n的路径,把这条路径上的xor和作为ans初值(先不管为什么可行),然后我们的任务就变成了求若干个环与这个ans初值所能组合成的xor最大值。显然,我们需要预处理出图上所有的环,并处理出所有环的环上xor值,这当然是dfs寻找,到n的路径的时候顺便求一下就可以了。

  当我们得到了若干个环的xor值之后,因为是要求xor最大值,我们就可以构出这所有xor值的线性基。构出之后,再用ans在线性基上取max就可以了。

  现在我们来讨论上述做法的可行性。

   第一种情况:我们对最终答案产生贡献的某个环离1到n的主路径很远,这样的话,因为至少可以保证1可以到达这个环,那么我们可以走到这个环之后绕环一周之后原路返回,这样从1走到环的路上这一段被重复经过所以无效,但是环上的xor值被我们得到了,所以我们并不关心这个环和主路径的关系,我们只关心环的权值。

  第二种情况:我们任意选取的到n的路径是否能保证最优性。假设存在一条更优的路径从1到n,那么这条路径与我们原来的路径构成了一个环,也就会被纳入线性基中,也会被计算贡献,假如这个环会被经过,那么最后的情况相当于是走了两遍原来选取的路径,抵消之后走了一次这个最优路径,所以我们无论选取的是哪条路径作为ans初值,都可以通过与更优情况构成环,然后得到一样的结果。这一证明可以拓展到路径上的任意点的路径选取。

  这样我们就可以完美解决了。我第一次WA了一发,因为我没有考虑到ans初值不为0,在线性基上取到xor的max的时候,不能单纯以ans这一位是否为0来决定是否异或上基的这一位,必须要看异或之后取一个max做一个判断才行。

 

3、codeforces724G

  直接链接到我的那篇博客过去辣

原文地址:https://www.cnblogs.com/DWVictor/p/10317095.html

时间: 2024-08-29 19:36:54

线性基(一的相关文章

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

HDU 3949 XOR(线性基)

题意:给出一组数,求最小的第k个由这些数异或出来的数. 先求这组数的线性基.那么最小的第k个数显然是k的二进制数对应的线性基异或出来的数. # include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include <vector> # include <queue> # include <stack> # includ