题目链接

如何求线性基中第K小的异或和?好像不太好做。

如果我们在线性基内部Xor一下,使得从高到低位枚举时,选base[i]一定比不选base[i]大(存在base[i])。

这可以重构一下线性基,从高到低位枚举i,如果base[i]在第j位(j<i)有值,那么Xor一下base[j]。(保证每一列只有一个1)

比如 1001(3)与0001(0),同时选0,3只比3要小;重构后是 1000(3)和0001(0),这样同时选0,3比只选0或3都要大。

这样将K二进制分解后就可以直接对应上线性基对应位的选择了。要存base[i]有值的i。

需要注意如果线性基中表示的向量不足n个,说明一定存在一组向量满足线性相关关系,即存在Xor和为0的情况。这样要使K减1。

判断是K>=(1<<size),线性基和的个数是2^{size}-1(不算0)。

#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 100000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
#define Bit 51
typedef long long LL;
const int N=1e5+5; int n,size,cnt;
LL base[69],b2[69];
char IN[MAXIN],*SS=IN,*TT=IN; inline LL read()
{
LL now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline void Insert(LL x)
{
for(int i=Bit; ~i; --i)
if(x>>i & 1)
if(base[i]) x^=base[i];
else {base[i]=x, ++size; break;}
}
inline LL Query(LL K)
{
LL ans=0;
for(int i=cnt; ~i; --i)
if(K>>i & 1) ans^=b2[i];
return ans;
}
void Rebuild()
{
for(int i=Bit; ~i; --i)
for(int j=i-1; ~j; --j)
if(base[i]>>j & 1) base[i]^=base[j];
for(int i=0; i<=Bit; ++i) if(base[i]) b2[cnt++]=base[i];
} int main()
{
n=read();
for(int i=1; i<=n; ++i) Insert(read());
Rebuild();
for(int Q=read(); Q--; )
{
LL K=read()-(size!=n);//别在for里开int啊mmp
printf("%lld\n",(K>=(1ll<<size))?-1ll:Query(K));
}
return 0;
}

有一种不需要重构线性基的方法:询问时将K二进制拆分(按size位),若K在第j位有1,且当前答案在第i位没有1(还可以更大)或是 K在第j位没有1,且当前答案在第i位有1(偏小?),则ans^=base[i]。

不太理解。(随大流吧。。)

#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 100000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
#define Bit 51
typedef long long LL;
const int N=1e5+5; int n,size;
LL base[69];
char IN[MAXIN],*SS=IN,*TT=IN; inline LL read()
{
LL now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline void Insert(LL x)
{
for(int i=Bit; ~i; --i)
if(x>>i & 1)
if(base[i]) x^=base[i];
else {base[i]=x, ++size; break;}
}
inline LL Query(LL K)
{
LL ans=0;
for(int i=Bit,now=size; ~i; --i)
if(base[i])
if((K>>(--now) & 1)^(ans>>i & 1)) ans^=base[i];
return ans;
} int main()
{
n=read();
for(int i=1; i<=n; ++i) Insert(read());
for(int Q=read(); Q--; )
{
LL K=read()-(size!=n);
printf("%lld\n",(K>=(1ll<<size))?-1ll:Query(K));
}
return 0;
}

LOJ.114.K大异或和(线性基)的更多相关文章

  1. Loj 114 k大异或和

    Loj 114 k大异或和 构造线性基时有所变化.试图构造一个线性基,使得从高到低位走,异或上一个非 \(0\) 的数,总能变大. 构造时让任意两个 \(bas\) 上有值的 \(i,j\) ,满足 ...

  2. [LOJ#114]k 大异或和

    [LOJ#114]k 大异或和 试题描述 这是一道模板题. 给由 n 个数组成的一个可重集 S,每次给定一个数 k,求一个集合 T⊆S,使得集合 T 在 S 的所有非空子集的不同的异或和中,其异或和  ...

  3. 【loj114】k大异或和 线性基+特判

    题目描述 给由 $n​$ 个数组成的一个可重集 $S​$ ,每次给定一个数 $k​$ ,求一个集合 $T⊆S​$ ,使得集合 $T​$ 在 $S​$ 的所有非空子集的不同的异或和中,其异或和 $T_1 ...

  4. LibreOJ #114. k 大异或和

    二次联通门 : LibreOJ #114. k 大异或和 /* LibreOJ #114. k 大异或和 WA了很多遍 为什么呢... 一开始读入原数的时候写的是for(;N--;) 而重新构造线性基 ...

  5. 【线性基】51nod1312 最大异或和&LOJ114 k大异或和

    1312 最大异或和 题目来源: TopCoder 基准时间限制:1 秒 空间限制:131072 KB 分值: 320 难度:7级算法题   有一个正整数数组S,S中有N个元素,这些元素分别是S[0] ...

  6. LOJ114 k大异或和

    传送门 (vjudge和hdu也有但是我觉得LOJ好看!而且限制少!) 不过本题描述有误,应该是k小. 首先我们需要对线性基进行改造.需要把每一位改造成为,包含最高位的能异或出来的最小的数. 为啥呢? ...

  7. 第k大异或值

    这道题与2018年十二省联考中的异或粽子很相像,可以算作一个简易版: 因为这不需要可持久化: 也就是说求任意两个数异或起来的第k大值: 首先把所有数放进trie里. 然后二分答案,枚举每个数,相应地在 ...

  8. LOJ #113. 最大异或和 (线性基)

    题目链接:#113. 最大异或和 题目描述 这是一道模板题. 给由 \(n\) 个数组成的一个可重集 \(S\),每次给定一个数 \(k\),求一个集合 \(T \subseteq S\),使得集合 ...

  9. BZOJ 4671 异或图 | 线性基 容斥 DFS

    题面 Description 定义两个结点数相同的图 G1 与图 G2 的异或为一个新的图 G, 其中如果 (u, v) 在 G1 与 G2 中的出现次数之和为 1, 那么边 (u, v) 在 G 中 ...

随机推荐

  1. iphone清除数字链接

    <meta name="format-detection" content="telephone=no">

  2. 弗罗贝尼乌斯範数(Frobenius norm)

    弗罗贝尼乌斯範数 对 p = 2,这称为弗罗贝尼乌斯範数(Frobenius norm)或希尔伯特-施密特範数( Hilbert–Schmidt norm),不过后面这个术语通常只用于希尔伯特空间.这 ...

  3. ctime 时间

    1. 类型clock_t: 是个long型,用来记录一段时间内的时钟计时单元数,即CPU的运行单元时间.size_t: 标准C库中定义的,应为unsigned int,在64位系统中为long uns ...

  4. 网站发布IIS后堆栈追踪无法获取出错的行号

    一.问题起因 系统发布上线后,有时会发生错误,那么错误的记录就很重要,它对于错误的排查和问题的发现有着重要的作用,通常我们采取的方式为Log日志文件记录和数据库错误记录.文本不会讨论错误记录的方式以及 ...

  5. weblogica 启动managed server 不用每次输入密码

    [weblogic@node2 AdminServer]$ pwd /home/weblogic/Oracle/Middleware/Oracle_Home/user_projects/domains ...

  6. 【黑客免杀攻防】读书笔记14 - 面向对象逆向-虚函数、MFC逆向

    虚函数存在是为了克服类型域解决方案的缺陷,以使程序员可以在基类里声明一些能够在各个派生类里重新定义的函数. 1 识别简单的虚函数 代码示例: #include "stdafx.h" ...

  7. 83.Linux之ubuntu-14.04.4-desktop-amd64安装

    QQ(1044233591) 一.软件下载 二.安装 1.上一节已经安装好了VMware10.0.4软件,双击桌面VMware Workstation软件图标,出现VMware软件界面,点击" ...

  8. 通过PDB文件实现非嵌入式的c++反射

    上一篇blog我阐述了一种实现非嵌入式的反射的基本思路.相比于通过宏和模板实现,这种非嵌入的反射的优点是不需要写额外的代码来记录meta信息. 首先,为了在c++中实现反射系统,我认为需要解决以下两个 ...

  9. Resouce, platform_device 和 platform_driver 的关系【转】

    转自:http://blog.csdn.net/uruita/article/details/7278313 從2.6版本開始引入了platform這個概念,在開發底層驅動程序時,首先要確認的就是設備 ...

  10. kworker内核工作队列详解

    工作队列是另一种将工作推后执行的形式,它可以把工作交给一个内核线程去执行,这个下半部是在进程上下文中执行的,因此,它可以重新调度还有睡眠.    区分使用软中断/tasklet还是工作队列比较简单,如 ...