网上大佬写的博客。。。我以为自己看懂了(假装看懂)。。。结果第二题就被卡住了。。。看不懂了。。

https://blog.sengxian.com/algorithms/linear-basis

https://www.cnblogs.com/vb4896/p/6149022.html

是我水平不够,看起来有点费劲(;´༎ຶД༎ຶ`)智商堪忧

还是视频看起来轻松很多:青涩的讲解,但是能听懂,给up主点赞!

目前的理解:线性基就是通过异或构建行阶梯矩阵,找到最大线性无关的向量组,去解决有关XOR的一些问题

数x对应的二进制为: bj=0或者1,用p[]存下面矩阵中的数

所谓线性基,就是线性代数里面的概念。一组线性无关的向量便可以作为一组基底,张起一个线性的向量空间,这个基地又称之为线性基。

第一个例子:


,插入的时候从高位向低位看起

--->插入a[0]=7=0111:a[0]的=0,p[2]=a[0]

矩阵:

--->插入a[1]=2=0010:a[1]的=1,p[1]=a[1],后面的位k,若,那么p[1]^=p[k](p[k]的),消掉p[1]中后的1,让p[1]中只有=1;同理,p[1]上面的行j,如果p[j]中的=1,那么p[j]^=p[1],消掉p[j]中位上的1,保证p[j]中只有

矩阵:

--->插入a[2]=3=0011,从高位向低位看起,因为=1的位置已经存入数a[1]了,所以为了保证我们要构建的是行阶梯矩阵,a[2]^=p[1],新的a[2]=0001,其中,p[0]=a[2],和插入a[1]时相同的做法,用下面的行消去自己,用自己消去上面的行中不应该为1的1:

矩阵:

--->插入a[3]=4=0100,,但是p[2]已经存入数了,a[3]^=p[2]=0,无法插入

至此,线性基对应的行阶梯矩阵已经构建完了,此外,通过构建过程可以知道最终的矩阵可以转化为如下内容:

p[2]、p[1]、p[0]都不为0,所以线性基的大小为num=3,a[4]中n=4,num<n

p[2]、p[1]、p[0]对应的向量是一个最大线性无关的向量组,因为num<n所以a[]中的数可以通过异或得到0,这点可以通过插入a[3]时出现0得到验证。当num=n时,这n个向量组成最大线性无关的向量组,根据线性无关的定义可以知道只有这些向量前面的系数都为0时才可以得到0。

注意:这里的p[2]、p[1]、p[0]进行异或相当于其对应的向量进行加法运算(二进制加法,没有进位)。

用新的数组L(或者一个vector<>)存不为0的p[i],若求a[4]所能构成的异或的数中的第k小,k=,新的矩阵有如下对应关系:

若求第k=1小,因为num!=n,所以可以异或出0,那么可异或出第1小的数就是0

若求第k=4小,因为num!=n,所以可以异或出0,所以k=k-1=3=0011,,那么可异或出第1小的数就是L[0]^L[1]等价于

第二个例子:


--->插入a[0]=9=1001,p[3]=a[3]

矩阵:

--->插入a[1]=11=1011,p[3]已经有数了,a[1]^=p[3]=0010,p[1]=a[1],用下面的行消自己,用自己消下面的行(但都莫得消)

矩阵:

--->插入a[2]=5=0101,p[2]=a[2],用下面的行消自己,用自己消下面的行(但都莫得消)

矩阵:

最终的矩阵相当于:其中线性基的大小num=3,n=3

用新的数组L存不为0的p[i],求a[3]能异或成的第k小,k=:,对应关系如下:

因为线性基大小num=n,所以不能异或出0

若k=1=0001,,所以第1小的数就是L[0]

若k=5=1001,,所以第5小的数就是L[0]^L[3]

综上所述:


 构建行阶梯矩阵时,若a[i]=,从高位往地位第一个为1的位是j,若p[j]已经存入数了,那么a[i]^=p[j],否则直接p[j]=a[i]

 在p[j]插入a[i]后,让p[j]下面的行消去p[j]中j位后面的1,让p[j]消去p[j]上面的行中j位上的1,目的是为了尽量使p[j]中只有j位是1

 若n个数构成的线性基的大小num=n,则对应的行阶梯矩阵的秩=n,这n个向量线性无关,那么这个n个数不能通过异或得到0,否则可以得到0

 在求n个数通过异或构成的第k小的数时,用新的数组L(或者 vector<>)存那些不为0的p[i]

     num==n,不能得到0,第k小的数就是k的二进制位上为1的位所对应的L[]值,比如K=1001,那么结果就是L[0]^L[3]

     num!=n,不能得到0,k=k-1,结果就是k的二进制位上为1的位所对应的L[]值

     num==n时,这个n个数最多能构成-1个不同的数;否则可以构成个不同的数

 L[i]^L[j]或者p[i]^p[j] 其实就是a[]上的一些数在异或,只不过目前我们不关心是哪些数在异或(当然也可以通过记录得知),我们只在意能异或成的数的大小

 求n个数能构成的最大值,就直接把L[]中的值都异或起来就OK啦!

终于写完原理了٩(˃̶͈̀௰˂̶͈́)و总算是懂了线性基了☆〜(ゝ。∂)

一般1≤a[i]≤1e18,最多60位,所以max_base设成60,p[max_base+3],max_base别设置太大了,可能结果会错,我试过(´・Д・)」,就60吧!

模版:


hdoj3949

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e4+5;
const int max_base=60;
ll t,n,q,x;
ll a[maxn],p[maxn+3];
vector<ll> v;
void solve()
{v.clear();//清空啊啊啊!!!memset(p,0,sizeof(p));//初始化啊啊啊!!!for(int i=0;i<n;i++){for(int j=max_base;j>=0;j--)//从高位向低位{if(a[i]>>j==0) continue;//该位上为0,对线性基这位没有有贡献if(!p[j])//该行没数,直接填入{p[j]=a[i];for(int k=j-1;k>=0;k--)if(p[k] && p[j]>>k&1)p[j]^=p[k];//下面的行消自己for(int k=j+1;k<=max_base;k++)if(p[k]>>j&1)p[k]^=p[j];//自己消上面的行break;//填入之后结束每一位上的遍历}elsea[i]^=p[j];//该行已经有数}}for(int i=0;i<=max_base;i++)if(p[i])v.push_back(p[i]);}
ll query(ll x)
{if(v.size()!=n) x--;if(x==0) return 0;//能得到0,第1小的数是0if(x>=(1LL<<v.size())) return -1;//能得到0,x已经-1了,x最多达到2^v.size()-1;不能得到0,x最多就是v.size()-1ll ans=0;for(int i=0;i<=max_base;i++)if(x>>i&1)ans^=v[i];return ans;
}
int main()
{//freopen("/Users/zhangkanqi/Desktop/11.txt", "r", stdin);scanf("%lld",&t);for(int i=1;i<=t;i++){printf("Case #%d:\n",i);scanf("%lld",&n);for(int j=0;j<n;j++)scanf("%lld",&a[j]);solve();scanf("%lld",&q);for(int j=0;j<q;j++){scanf("%lld",&x);printf("%lld\n",query(x));}}return 0;
}

SGU275:但是好像没法补题,求n个数异或得到的最大值,直接把非0的p[i]异或起来就完事了

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e4+5;
const int max_base=60;
ll n;
ll a[maxn],p[maxn+3];
void solve()
{for(int i=0;i<n;i++){for(int j=max_base;j>=0;j--)//从高位向低位{if(a[i]>>j==0) continue;//该位上为0,对线性基这位没有有贡献if(!p[j])//该行没数,直接填入{p[j]=a[i];for(int k=j-1;k>=0;k--)if(p[k] && p[j]>>k&1)p[j]^=p[k];//下面的行消自己for(int k=j+1;k<=max_base;k++)if(p[k]>>j&1)p[k]^=p[j];//自己消上面的行break;//填入之后结束每一位上的遍历}elsea[i]^=p[j];//该行已经有数}}
}
int main()
{//freopen("/Users/zhangkanqi/Desktop/11.txt", "r", stdin);ll ans=0;scanf("%lld",&n);for(int i=0;i<n;i++)scanf("%lld",&a[i]);solve();for(int i=0;i<=max_base;i++)if(p[i])ans^=p[i];printf("%lld\n",ans);return 0;
}

【算法笔记+SGU275+HDU3949】线性基(XOR,求n个数异或得到的第k小的数)相关推荐

  1. hdu 3949(线性基模版) 异或和中第k小的数

    传送门 给定 n(n \le 10000)n(n≤10000) 个数 a_1, a_2, \ldots, a_na​1​​,a​2​​,-,a​n​​,以及 Q(Q\le 10000)Q(Q≤1000 ...

  2. hdu3949(线性基,求第k小的异或和

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3949 XOR Time Limit: 2000/1000 MS (Java/Others)    Me ...

  3. 【CodeForces 1100F】异或线性基 | 贪心 | 离线区间最大异或和 | E

    补题ing- 真的不应该错过这场比赛的 qwq 1100F. Ivan and Burgers time limit per test: 3 seconds memory limit per test ...

  4. 两个有序数组合起来求第k小的数+左老师专访ACM大神(笔记)8月5日斗鱼直播实录

    1.长度相等的两个有序数组寻找上中位数 注:上中位数1 2 3 4 5 6为3(偶数两个中位数为前面那个) 思路:去掉不可能为上中位数的,剩下的简化组合求上中位数. 1.1 奇数序列 位置 位置 位置 ...

  5. python递归算法 电影院票价问题_算法课堂实验报告(二)——python递归和分治(第k小的数,大数乘法问题)...

    python实现递归和分治 一.开发环境 开发工具:jupyter notebook 并使用vscode,cmd命令行工具协助编程测试算法,并使用codeblocks辅助编写C++程序 编程语言:py ...

  6. 第K小的数BFPRT算法

    介绍 BFPRT是解决求一个数组中第K小的数的算法,可以时间O(N)的时间复杂度,而使用排序求第K小的数的算法的时间复杂度为O(NlogN),因此BFPRT算法更加高效 思想 (1)分组:将原数组每五 ...

  7. 分治算法求解列表中第k小的数

    分治算法地思想就是将复杂问题分解为简单的子问题,然后寻求子问题的地归结,并组合各个子问题的解一起得到最终复杂问题的解. 针对求解列表中第k小的数,暴力拆解法可以将列表排序然后根据索引求出列表中第k小的 ...

  8. 算法导论:快速找出无序数组中第k小的数

    题目描述: 给定一个无序整数数组,返回这个数组中第k小的数. 解析: 最平常的思路是将数组排序,最快的排序是快排,然后返回已排序数组的第k个数,算法时间复杂度为O(nlogn),空间复杂度为O(1). ...

  9. java 寻找和为定值的多个数_算法笔记_037:寻找和为定值的两个数(Java)

    1 问题描述 输入一个整数数组和一个整数,在数组中查找两个数,满足他们的和正好是输入的那个整数.如果有多对数的和等于输入的整数,输出任意一对即可.例如,如果输入数组[1,2,4,5,7,11,15]和 ...

  10. 求n个数中的最大或最小k个数

    //求n个数中的最小k个数         public static void TestMin(int k, int n)         {             Random rd = new ...

最新文章

  1. 京津冀青少年网球分级赛总决赛开打 118名选手对决
  2. __name__=='__main__'的理解和使用
  3. 91. 最短Hamilton路径【状压DP】
  4. powershell如何编程C语言,如何用C语言执行powershell命令
  5. Rabbit寻宝记(1)
  6. Ubuntu18.04彻底删除MySQL数据库
  7. 学习记录-交叉编译环境的设置
  8. code block怎样实现图形界面_Python 代码实现验证码识别,很稳
  9. cube一站式云原生机器学习平台-加速分布式任务的运行效率
  10. 测试管理中的一个问题—功能点覆盖还是功能测试点覆盖
  11. 怎样制作动图gif?GIF生成器帮你一键制作gif
  12. 【Axure报错】-Unable to connect to Axure Share. Please make sure you have an internet connection and try
  13. qt 飞扬青云_Qt编写图片及视频TCP/UDP网络传输
  14. react devtools插件报错处理
  15. unbuntu20.0.4 显卡驱动安装,nividia-smi无效
  16. Android开机启动流程
  17. 惠普硬盘测试工具_短DST未通过,详细教您惠普笔记本如何检测硬盘
  18. js 爱心随鼠标移动 产生 并 消散 (源码)
  19. Oracle中创建和使用触发器Trigger
  20. FMDB - 数据库操作

热门文章

  1. C语言实现数字串转数字
  2. 【SpringBoot_ANNOTATIONS】属性赋值 02 @PropertySource赋值
  3. ARM开发7.3.4 基础实训( 4 ) 矩阵式键盘的输入系统设计--LPC21XX
  4. android 文件上传参数,Android OkHttp Post上传文件并且携带参数实例详解
  5. workbench表头可以是中文_超简单:Python 5步去中国式报表表头
  6. 外包以小时计算金额的费用_全了!各大税种的计算公式,建议收藏!
  7. 编写可维护的 JavaScript
  8. Android动画之补间动画详解
  9. powershell 模拟IE行为
  10. WAN killer