当前位置: 首页 > news >正文

力扣周赛困难-3681. 子序列最大 XOR 值 (线性基)

3681. 子序列最大 XOR 值 (线性基)

leetcode-子序列最大 XOR 值 (线性基)
qwen-image

简单的推导之后, 我们就可以把这个问题转化为一个经典的 线性基问题:

在题目中的条件下, 可以选中两个子序列, 然后一起做XOR, 那么我们可以理解为, 对于每个数字, 可以在 XOR 中出现 0/1/2 次数, 但是因为 a XOR a = 0, 所以说出现2次等价于出现0次, 于是对于每个数字, 可以在 XOR 中出现 0/1 次, 这就成为了经典问题:
求一个数组的子序列的最大异或值

线性基

参考资料:

  1. 灵茶山艾府-线性基【力扣周赛 460】
  2. oiwiki-线性基

首先, 我们考虑这样一个问题, 对于二维空间中的向量, 我们如何进行"表出".

如果用过去所学的正交分解法, 比如向量 v=⃗(5,6)v \vec = (5, 6)v=(5,6) 实质上就表出了 v⃗=5⋅i⃗+6⋅j⃗\vec v = 5 \cdot \vec i + 6 \cdot \vec jv=5i+6j, 其中的 i⃗,j⃗\vec i, \vec ji,j 就是两个线性基;

可以证明的是, 二维空间中的所有向量都可以用这样的两个线性无关的基向量来进行表出, 这里的表出指的是: 对任意的 t, 总存在 λ1,λ2∈R\lambda_1, \lambda_2 \in Rλ1,λ2R 使得 t⃗=λ1⋅i⃗+λ2⋅j⃗\vec t = \lambda_1 \cdot \vec i + \lambda_2 \cdot \vec jt=λ1i+λ2j;
同样可以证明, 对于 n 维空间, 所有向量都可以用符合条件的 n 个线性无关的基向量来进行表出

上面我们所说的情况是 加法 的情况, 那么对于 按位异或 是不是有类似的性质呢?

不严谨的证明, 可以做一波高斯消元, 然后得到的就是 a1=(1,0,0)...a_1 = (1,0,0)...a1=(1,0,0)..., 然后高斯消元的过程中, 即使一个东西出现了多次, 也可以直接做 %2 就可以得到, 确保每一个数字都是可以被"表出"出来的, 这里的表出就变成了: 对于任意的 n 位(也是维度) 向量 t 来说, 总是存在 λ1,...,λn∈{0,1}\lambda_1, ..., \lambda_n \in \{0, 1\}λ1,...,λn{0,1}, 使得 t⃗=∑i=1i=nλiei⃗\vec t = \sum_{i=1}^{i=n} \lambda_i \vec {e_i}t=i=1i=nλiei

接下来, 我们关注的就是线性基如何去构造:

由上面可知, 我们 32位 二进制数对应的是 32 维线性空间, 所以最多存在 32 个线性基, 于是我们可以用 int s[32] 来维护32个线性基.
下面的问题是, 如何遍历一些数字, 快速判断出它是否能被目前维护的线性基 表出; 一个巧妙的办法是, 确保每一个基的最高位1的位置都不同, 当尝试插入一个新的数字时, 我们将该数字从高位数到低位数进行考察, 比如该数字的第 i 位是1, 此时有两种情况:

  1. 最高位是第 i 位的线性基还没有找到, 这时我们一定可以将该数字添加到线性基中;
  2. 最高位是第 i 位的线性基找到了, 这个时候我们虽然不能立刻得知插入数字是否可以被表出, 但是我们可以通过 new_num = new_num ^ s[i]new_num 退化, 最高位数就会降低, 如果最后退化成了0, 那么就相当于被成功表出, 否则一定会走1添加进去

代码如下:

int s[32] = {};
int size = nums.size();for (int i = 0; i < size; i++) {// for (int bit = 31; bit >= 0; bit--) {// 这里表示位数if (nums[i] & 1 << bit) {// 最高位确实是 bitif (s[bit] == 0) {s[bit] = nums[i];break;} else {// 否则, 做一下异或, 然后接着向下看nums[i] ^= s[bit];}}}
}

接下来, 我们关注的是, 这样去构造的线性基的特点, 并且这个特点直接导致我们后面可以使用贪心算法

因为这个线性基, 可以确保上面的最高位各不相同, 那么我们就自然可以使用贪心, 尽可能取用高位1;

int ans = 0;
for (int i = 31; i >= 0; i--) {if ((ans ^ s[i]) > ans) {ans ^= s[i];}
}

ps: 位运算的优先级问题需要注意, 一般来说位运算的优先级是比较低下的, 所以需要加上括号, 比如说: ans ^ s[i] > ans 必须写成是 (ans ^ s[i]) > ans

ps: 线性基合并 / 线性基求交问题
  1. 合并, A 向 B 插入即可
  2. 求交, A 尝试向 B 插入:
    1. 如果 αi\alpha_iαi 最后退化成0, 说明可以被 B 表出, 那么加入交集;
    2. 如果没有退化成0, 说明不可以被 B 表出, 那么加入 B 中(用来表出后续的 αi+1\alpha_{i+1}αi+1)

文章转载自:

http://Gyn2RVNW.bwrbm.cn
http://DMLa6NUm.bwrbm.cn
http://scecT7Kb.bwrbm.cn
http://EXQaHsz3.bwrbm.cn
http://jV1EFxhF.bwrbm.cn
http://6NCQMEa9.bwrbm.cn
http://ILooKplR.bwrbm.cn
http://YhpODb2f.bwrbm.cn
http://vF8wc78Q.bwrbm.cn
http://pm4t3vjq.bwrbm.cn
http://W4m5vJ4a.bwrbm.cn
http://3jyLUEk9.bwrbm.cn
http://RzovbDHg.bwrbm.cn
http://T3YoSRQR.bwrbm.cn
http://WGALMDZ0.bwrbm.cn
http://lAAURYM9.bwrbm.cn
http://QTHDQfQQ.bwrbm.cn
http://wK2qj2j7.bwrbm.cn
http://cWlj8w7G.bwrbm.cn
http://9NCctJhX.bwrbm.cn
http://VWhbxyPA.bwrbm.cn
http://yazYhuFT.bwrbm.cn
http://F5X0ouXL.bwrbm.cn
http://ZdbclPWl.bwrbm.cn
http://kmuGc4CE.bwrbm.cn
http://37XJQurz.bwrbm.cn
http://ouWk7Naf.bwrbm.cn
http://HgqADOO0.bwrbm.cn
http://b31tvgIp.bwrbm.cn
http://oaTjHMdZ.bwrbm.cn
http://www.dtcms.com/a/387144.html

相关文章:

  • Spring IOC 与 Spring AOP
  • 【FreeRTOS】队列API全家桶
  • 【Docker项目实战】使用Docker部署Cup容器镜像更新工具
  • (笔记)内存文件映射mmap
  • springboot传输文件,下载文件
  • 基于51单片机的出租车计价器霍尔测速设计
  • 【笔记】Agent应用开发与落地全景
  • C++ STL底层原理系列学习路线规划
  • LAN口和WAN口
  • Dify + Bright Data MCP:从实时影音数据到可落地的智能体生产线
  • 数据库--使用DQL命令查询数据(二)
  • 【FreeRTOS】创建一个任务的详细流程
  • CKA06--storageclass
  • 宝塔安装以及无法打开时的CA证书配置全攻略
  • wend看源码-Open_Deep_Research(LangChain)
  • 摄像头文档识别与透视变化技术和背景建模技术(追踪)
  • 123、【OS】【Nuttx】【周边】效果呈现方案解析:find 格式化打印
  • DC-4靶机渗透
  • 大模型在线对话平台集锦(持续更新ing...)
  • JavaScript中 i++ 与 ++i
  • 【cookie】JavaScript操作增删改查
  • OC-AFNetworking
  • Java全栈学习笔记35
  • kylin v10 系统 上 qt 5.15.17版本构建及使用
  • Linux:基于环形队列的生产者消费模型
  • Nginx 配置 Vue 项目 Hash/History 模式路由跳转错误的解决方案
  • Linux Makefile与进度条
  • 硬件驱动——I.MX6ULL裸机启动(3)(按键设置及中断设置
  • 深度学习基本模块:RNN 循环神经网络
  • 【深度学习】PixelShuffle处理操作