【题解】魔改版线性基

魔改版线性基解决此类问题。

联系线性空间的性质,我们直接可以构造出这样的基:

\[100000
\\
010000
\\
000010
\\
000001
\]

使得每个基的最高位是唯一的,我们的目的是要能够保证从上往下一直异或一直变大,所以不能使基出现这样的情况:

\[100001
\\
000001
\]

一个不能从上往下一直异或一直变大的例子。

考虑如何构造\(kth\) 大(小),考虑这样的性质,我们记\(a_i\)表示从下往上第\(i\)个基,显然从\(0\)开始,如果我们异或了\(a_x\),那么我们可以保证我们会比这个线性空间内\(2^{x-1}\)个值都要大,直接考虑从上往下查询,类似树上倍增。

考虑无解的情况,显然当我们发现\(k \ge 2^{|E|}\)时就无解了。

然而我们有一个问题,那就是我们默认\(0\)是可以被表示出来的,然而我们知道,当给定元素全部互为不相关时,这个时候就不存在一个\(0\)会被表示出来了。那么我们可以特判一下即可 。

好,那么如何构造从上往下一直异或一直变大的基呢?魔改一下就好了。具体看代码。

分析复杂度:我们把魔改操作的\(log^2\)看做常数吧...那就是\(O(nlogn)\)

当然你如果不承认魔改操作是常数,那就继续魔改\(upd\)函数,也可以做到\(nlogn\)。具体就是加入的时候从小往大加。

下面的第\(k\)小,转换为第\(k\)大用\(2^{|E|}​\)减去即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template <class ccf>
inline ccf qr(ccf ret) {
ret = 0;
register char c = getchar();
while (c < 48 || c > 57) c = getchar();
while (c >= 48 && c <= 57) ret = ret * 10 + c - 48, c = getchar();
return ret;
}
namespace bs {
ll num[51], sav[51];
struct BASE {
ll data[51];
int cnt;
ll p;
BASE() {
memset(data, 0, sizeof data);
cnt = 0;
p = 1;
}
inline ll size() { return 1LL << cnt; }
inline void set() {
for (register int t = 1; t <= 50; ++t)
if (data[t])
for (register int i = t + 1; i <= 50; ++i)
if (data[i] & num[t])
data[i] ^= data[t];
}
inline void upd(ll x) {
for (register int t = 50; t >= 1; --t) {
if (x & num[t]) {
if (not data[t]) {
data[t] = x;
++cnt;
break;
} else
x ^= data[t];
}
if(not x) {
p=0;
break;
}
}
}
inline ll que(ll k) {
register ll ret = 0, sav = 0;
if(cnt==50) --k;
if (k > this->size())
return -1;
for (register int t = 50, f = 0; t >= 1; --t) {
if (data[t]) {
++f;
if (sav + (1LL << (cnt - f)) <= k)
sav += 1LL << (cnt - f), ret = ret ^ data[t];
}
}
return ret;
}
inline void clear() {
memset(data, 0, sizeof data);
cnt = 0;
}
inline void debug() {
for (register int t = 50; t >= 1; --t) {
if (data[t])
cout << ((bitset<10>)data[t]) << ' ' << data[t] << endl;
}
cout << endl;
}
};
inline void init() {
for (num[0] = 2, num[1] = 1; num[0] <= 50; ++num[0]) num[num[0]] = num[num[0] - 1] << 1;
}
}
bs::BASE qaq; int main() {
bs::init();
int n = qr(1);
for (register int t = 1; t <= n; ++t) qaq.upd(qr(1ll));
int m = qr(1);
qaq.set();
for (register int t = 1; t <= m; ++t) printf("%lld\n", qaq.que(qr(1ll)));
return 0;
}

【题解】kth异或和/魔改版线性基的更多相关文章

  1. BZOJ4671 异或图(容斥+线性基)

    题意 定义两个结点数相同的图 \(G_1\) 与图 \(G_2\) 的异或为一个新的图 \(G\) ,其中如果 \((u, v)\) 在 \(G_1\) 与 \(G_2\) 中的出现次数之和为 \(1 ...

  2. 【题解】 Codeforces 662A Gambling Nim (线性基)

    662A,戳我戳我 Solution: 我们先取\(ans=a[1] \bigoplus a[2] \bigoplus ... \bigoplus a[n]\),然后我们定义\(c[i]=a[i] \ ...

  3. bzoj 2844 albus就是要第一个出场 异或和出现次数 线性基

    题目链接 题意 给定\(n\)个数,将其所有的子集(\(2^n\)个)的异或和按升序排列.给出一个询问\(q\),问\(q\)在该序列中第一次出现位置的下标(下标从\(1\)开始). 题解 结论 记其 ...

  4. BZOJ4671 异或图 斯特林反演+线性基

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4671 题解 半年前刚学计数的时候对这道题怀着深深的景仰,现在终于可以来做这道题了. 类似于一般 ...

  5. P5169 xtq的异或和(FWT+线性基)

    传送门 我咋感觉我学啥都是白学-- 首先可以参考一下这一题,从中我们可以知道只要知道两点间任意一条路径以及整个图里所有环的线性基,就可以得知这两个点之间的所有路径的异或和 然而我好像并不会求线性基能张 ...

  6. 题解——洛谷P3812【模板】线性基

    学了下线性基 使用好像并不复杂 打了板子 但是要注意位运算优先级 #include <cstdio> #include <algorithm> #include <cst ...

  7. 【题解】 luogu 3857 [TJOI2008]彩灯 (线性基)

    luogu3857,懒得复制 Solution: 裸的线性基,往里面添加数,记录添加个数\(sum\),快速幂输出\(2^{sum}\)即可 Code: //It is coded by Ning_M ...

  8. 【题解】 bzoj4004: [JLOI2015]装备购买 (线性基)

    bzoj4004,戳我戳我 Solution: 裸的线性基,这没啥好说的,我们说说有意思的地方(就是我老是wa的地方) Attention: 这题在\(luogu\),上貌似不卡精度,\(bzoj\) ...

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

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

随机推荐

  1. Topcoder SRM 668 DIV 2

    VerySecureEncryption 模拟 题意: 给你个串message,然后一个置换key,输出置换K次后的结果. 题解: 直接模拟就好. 代码: #include<iostream&g ...

  2. the Red Sun

    题面 Description 给定一张 N 个点的图, 点的标号为 1 到 n . 我们进行 M 次连边, 每次连边可以描述为 a b c d w : for i = a to b do for j ...

  3. Java Servlet Filter

    做web开发的人对于Filter应该不会陌生,一直在很简单的使用,但是一直没有系统的总结一下,随着年纪的慢慢长大,喜欢总结一些事情,下面说说我对Filter的理解,官方给出的Filter的定义是在请求 ...

  4. js对象浅拷贝和深拷贝详解

    js对象浅拷贝和深拷贝详解 作者:i10630226 字体:[增加 减小] 类型:转载 时间:2016-09-05我要评论 这篇文章主要为大家详细介绍了JavaScript对象的浅拷贝和深拷贝代码,具 ...

  5. Linux shell 提取文件名和目录名的一些方法(转)

    很多时候在使用Linux的shell时,我们都需要对文件名或目录名进行处理,通常的操作是由路径中提取出文件名,从路径中提取出目录名,提取文件后缀名等等.例如,从路径/dir1/dir2/file.tx ...

  6. 从Android动画到贝塞尔曲线

    基础知识: 动画通过连续播放一系列画面,给视觉造成连续变化的图画.很通俗的一种解释.也很好理解.那么我们先来一个案例看看. 动画案例:百度贴吧小熊奔跑 效果: topic.gif 代码: <?x ...

  7. 版本控制工具:SVN和Maven的区别

    一.只有svn的情况 首先考虑没有maven的情况.这样的话,项目组每个开发人员,都需要在本地check out所有的源码. 每次提交之前,需要先更新周边工程的代码.由于工程之间是依赖的,所以很可能需 ...

  8. 微信小程序-上传多张图片加进度条(支持预览、删除)

    2018-12-24 详情示例见:https://www.cnblogs.com/cisum/p/9564898.html 2018-12-29 组件下载见:https://www.cnblogs.c ...

  9. 解决apt 依赖破损的问题

    在 安装 python3 / python2 共存的环境时, 不知道做了什么, 导致 apt 依赖故障 odoo@sy-odoo-08:~$ sudo apt-get remove apport 正在 ...

  10. Shell脚本值:运算符

    算术运算符 原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用. expr 是一款表达式计算工具,使用它能完成表达式的求值操作. 例如:实现两个 ...