首页 > 其他分享 >线性基详解

线性基详解

时间:2023-07-17 18:55:42浏览次数:29  
标签:ll 插入 异或 详解 ans 线性 a2

线性基详解

线性基主要用来解决异或问题

线性基的性质

  1. 原序列的任何一个数都可以由线性基中的若干个元素异或得到

  2. 线性基中的任何元素互相异或,不可异或出0

我们考虑到异或的性质:

  1. 交换律:如果a1 ^ a2 ^ a3 = a4 那么a2 ^ a1 ^ a3 = a4 很容易证明
  2. a1 ^ a2 = a3 则a1 ^ a3 = a2 两边同时异或a2 即可证明

线性基的构造

如何构造线性基呢,我们定义一个数组p[i]表示最高位在第i位上的数是多少,那这样构造为什么是对的呢,看一组例子:5 1 6 这一组数

它的线性基是多少呢,逐渐将每一个数插入线性基

p[2]=5,p[0]=1,当插入到6时,我们发现p[2]已经有值了 ,那如何插入这个6来保证线性基的正确性

考虑到异或的性质2:a1 ^ a2 = a3 则a1 ^ a3 = a2

如何保证在不损失6的情况下插入6,不妨让6^p[2],消除掉6的最高位,然后继续插入。考虑到异或的交换律,设p[2] ^ 6=x,那么新插入的这个数x,x ^ p[2]=6,由于线性基的性质1,从而保证了线性基插入的正确性。

伪代码:
void insert(ll *p,ll x)
{
for(int i=63;i>=0;i--)
{
if((x>>i)&1)
{
if(!p[i]){p[i]=x;break;}
else x^=p[i];
}
}
}

//p是线性基数组,x是插入的值

线性基的应用

一、判断一个数是否可以被一个序列异或出来

考虑到线性基的构造:

一个数被插入到线性基时,分为两种情况:

  1. 可以被插入线性基:

    假设插入数x,如果被插入到第i位,那么p[i]=x ^ p[a] ^ p[b] ^……p[z], a,b,c……代表i的更高位上p数组已经有值的位置

  2. 不能被插入线性基:

    为什么不能被插入,说明在x插入的时候,不断异或某些已经p数组有值的位置的过程中,变成了0,即x ^ p[a] ^ p[b] ^……p[z]=0,此时无法被插入到线性基。

一个数不能被插入线性基说明这个元素一定可以被这个线性基异或出来,也就是一定可以被这个序列某些元素异或出来,为什么呢,在插入的过程中x ^ p[a] ^ p[b] ^……p[z]=0,也就是p[a] ^ p[b] ^……p[z]=x。所以判断一个数是否可以被这个序列异或,只需要判断这个数是否可以插入到这个线性基里面。

为了方便起见,可以直接改写构造代码如下:

bool insert(ll *p,ll x)
{
for(int i=63;i>=0;i--)
{
if((x>>i)&1)
{
if(!p[i]){p[i]=x;break;}
else x^=p[i];
}
if(x==0)return false;
}
return true;
}

二、求一个序列的若干个元素异或的最大值

考虑到线性基数组是从高位到低位的,所以我们贪心从高位向低位异或即可的出答案

贪心的正确性:

假如现在的ans从高位向低位异或,异或到了第i位,分为两种情况

  1. 如果ans的二进制第i位不为1:

    那么ans ^ p[i] > ans,显而易见ans异或完之后第i位为1,一定变得更大。

  2. 如果ans的二进制第i位为1:

    那么ans ^ p[i] < ans,显而易见ans异或完之后第i位为0,一定变得更小。

所以如果ans ^ p[i] > ans就让ans异或p[i]

伪代码:

``ll maxans(ll *p) { ll ans=0; for(int i=63;i>=0;i--)//记得从线性基的最高位开始 if((ansp[i])>ans)ans=p[i]; return ans; }

三、求一个序列的若干个元素异或的最小值

显而易见答案为0或p[0]。

因为线性基异或不出0,所以如果原序列可以异或出0,那ans就是0,否则就是p[0],因为p[0]异或任何线性基中的元素都会变大

四、求一个序列的若干个元素异或的第k小值

二进制原理 ,先预先处理线性基数组,保证p[i]已经是这一位在线性基里面最小的,只要让p[i]的每一位异或上对应的位置,即可使其变得更小。

即,对于每一个p[i],枚举j=i-1到j=0,如果p[i]的第j位为1,那么p[i]异或上p[j]。

然后将k转化成2进制,再用2进制的1、0的位置异或即可。

详见代码:
void work(ll *p)
{
for(int i=63;i>=0;i--)
{
for(int j=i-1;j>=0;j--)
{
if((p[i]>>j)&1)p[i]^=p[j];
}
}
}//预处理
ll maxk(ll *p,ll k)
{
if(k==0&&flag)return 0;
//flag表示原序列可以异或0
if(flag)k--;
work();
ll ans=0;
for(int i=0;i<=63;i++)
{
if(p[i])
{
if(k&1)ans^=p[i];
k>>=1;
}
}
return ans;
}

标签:ll,插入,异或,详解,ans,线性,a2
From: https://www.cnblogs.com/xqys/p/17560931.html

相关文章

  • Java方法详解
    Java方法详解方法的定义Java方法是语句的集合,它们在一起执行一个功能方法是解决一类问题的步骤的有序结合方法包含于类或对象中方法在程序中被创建,在其他地方被引用publicclassDemo01{//main方法publicstaticvoidmain(String[]args){intsum......
  • Linux磁盘专题-linux文件系统详解
    这可是我几年前的杰作笔记呀.....当初手写计算都会,现在忘光光....物理硬盘Block的概念和作用硬盘底层一次IO就是读、写一次扇区,一个扇区默认是512Byte。读写大量文件如果以扇区为单位会很慢、性能不好,所以出现了逻辑块的概念(logicblock),也就是硬盘Block。逻辑块Block是......
  • 详解prettier使用以及与主流IDE的配合
    很多前端小伙伴在日常使用prettier的时候都或多或少有一点疑惑,prettier在每一个IDE中究竟是怎样工作起来的,为什么配置有时候生效,有时又毫无效果。为了让我们的前端小伙伴更加熟悉这块,本文将对prettier在主流IDE中的使用过程一探究竟。prettier是什么在介绍prettier如何集成到IDE......
  • 详解C#开发Android应用程序的流程
    Android系统一下子铺天盖地而来,让人目不暇接。兴奋的同时也让部分开发人员犯难了!要知道从熟知的Wince、Mobile开发语言C#跨越到RFID-Android的Java。可不是一朝一夕就能完成的。就好比你的乾坤大挪移已经第七层了,却忽然要你从易筋经从头练起,真是愁煞人也!难道微软的开发环境和谷歌......
  • 【后端面经-Java】JVM内存分区详解
    @目录1.JVM内存分区简介2.JVM栈3.JVM堆4.JVM方法区5.JVM内存分配实例面试模拟参考资料1.JVM内存分区简介JVM内存分区如图所示:主要有如下几个区域:栈(Stack)堆(Heap)方法区(MethodArea)程序计数器(PC)本地方法栈(NativeMethodStack)其中,程序计数器用于存储线程当前执行的......
  • 人工智能自然语言处理:N-gram和TF-IDF模型详解
    人工智能自然语言处理:N-gram和TF-IDF模型详解1.N-gram模型N-Gram是一种基于统计语言模型的算法。它的基本思想是将文本里面的内容按照字节进行大小为N的滑动窗口操作,形成了长度是N的字节片段序列。每一个字节片段称为gram,对所有gram的出现频度进行统计,并且按照事先设......
  • 线性表——栈与队列
    栈栈(stack):先进后出,后进先出的数据结构。栈是限定仅在表尾进行插入和删除操作的线性表。我们把允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom),不含任何数据元素的栈称为空栈。栈又称为后进先出(LastInFirstOut)的线性表,简称LIFO结构。需要注意,栈是一个线性表,也......
  • base64详解
    base64详解前置知识位与字节二进制系统中,每个0或1就是一个位(bit,比特),也叫存储单元,位是数据存储的最小单位。其中8bit就称为一个字节(Byte)。1B=8位位运算与运算:符号表示为&。运算规则:两位同时为“1”,结果才为“1”,否则为0或运算:符号表示为|。运算规则:两位只要有一位为......
  • axios详解以及完整封装方法
    """一、axios是什么Axios是一个基于promise网络请求库,作用于node.js和浏览器中。它是isomorphic的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生node.jshttp模块,而在客户端(浏览端)则使用XMLHttpRequests。axios有以下特性:从浏览器创建X......
  • 详解Python数据处理Pandas库
    pandas是Python中最受欢迎的数据处理和分析库之一,它提供了高效的数据结构和数据操作工具。本文将详细介绍pandas库的使用方法,包括数据导入与导出、数据查看和筛选、数据处理和分组操作等。通过代码示例和详细解释,帮助你全面了解和应用pandas库进行数据处理和分析。一、安装和导......