数学/数论专题-专项训练:线性基
1. 前言
本篇博文是作者学习线性基时候的一些专项训练。
因为作者是个 OIer,本文只讨论 OI 中常见的线性基。
阅读本文前请先确保学过线性基。
2. 练习题
题单:
P4301 [CQOI2013] 新Nim游戏
做这道题需要知道一个前置知识:传统 Nim 游戏的先手必败条件为 ⨁ i = 1 n a i = 0 \bigoplus_{i=1}^{n}a_i=0 ⨁i=1nai=0。
因此先手需要想个办法使得不管后手怎么拿,都组合不出 0。
而线性基具有如下两个性质:
- 线性基内的数不能异或出 0。
- 对于一个序列 d d d 而言,其线性基数的个数是固定的,不会因为插入数的顺序而改变。
因此我们可以考虑求一下原序列的线性基。
在求线性基的过程中我们会得到一些数插入失败,而这些数就是要被拿走的数,拿走之后剩下的数就不能异或出 0 了(因为线性基内的数不能异或出 0 了)。
题中要求取走火柴数尽量小,那么我们只需要将 a i a_i ai 从大到小排序就可以了。
Code:GitHub CodeBase-of-Plozia P4301 [CQOI2013] 新Nim游戏.cpp
P4151 [WC2011]最大XOR和路径
对于一条 1 → n 1 \to n 1→n 的路径,我们可以拆成两部分:一些环 + 一条链。
先不考虑链,求一下环能异或出的最大值。
我们可以搜索出所有的环,然后将这些环上的异或权值全部丢到线性基里面,那么对于求出来的线性基我们求个最大值就好了。
那么这一条链要怎么选呢?实际上这一条链可以随便选。
简单证明一下:
假设路径 B B B 比路径 A A A 更优,由于 A , B A,B A,B 共同构成了一个环,那么在异或线性基的时候 A A A 会异或上这个环,这样路径就变成了 B B B。
因此选哪条链是没差别的。
Code:GitHub CodeBase-of-Plozia P4151 [WC2011]最大XOR和路径.cpp
P5556 圣剑护符
首先我们需要转化一下查询操作的题意:查询两个不同子集其异或结果相同等价于查询是否有一个非空子集使得其异或结果为 0。
那么转化题意之后两个操作就变成了树上路径异或,树上路径查询。
发现查询操作可以使用线性基来维护。
哈?你跟我说这么多点都用线性基?
因此这道题我们需要一点类似于根号分治的思想。
发现值域为
[
0
,
2
30
)
[0,2^{30})
[0,230),因此线性基内数的个数至多只有 30 个,对于那些路径长度大于 30 的直接输出 YES
。
对于小于 30 的路径呢?由于数的数量很少,直接插入线性基不就好了。
因此现在我们整理一下查询做法:根据路径长度分类,大于 30 直接输出 YES
,否则就直接暴力线性基查询。
发现我们需要知道路径长度以及 LCA,这玩意貌似求个深度然后倍增就可以了。
但是因为存在修改操作,因此我们采用树链剖分。
没学过树链剖分的左转树链剖分 - OI Wiki。
好的那么现在认为你已经学会了树链剖分。
那么对于修改操作,树剖之后我们直接维护一棵线段树区间修改即可,由于异或满足交换律和结合律因此正确性是对的。
查询操作上面已经讲过了,但是因为我们已经树剖了因此求 LCA 和路径长度直接树剖查询即可。
然后这道题就做完了,注意一下线性基的清 0。
Code:GitHub CodeBase-of-Plozia P5556 圣剑护符.cpp
3. 总结
线性基大多考的还是思维和与别的算法结合,单独考线性基的题目并不多。
标签:专题,数论,路径,P4151,查询,异或,30,线性 来源: https://blog.csdn.net/BWzhuzehao/article/details/118818720
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。