嘟嘟嘟




集训的时候发现自己不会线性基,就打算学一下。

这东西学了挺长时间,其实不是因为难,而是天天上午考试,下午讲题,结果晚上就开始颓了。

今天总算是有大块的时间好好学了一遍。

这里推荐menci大佬的博客:线性基学习笔记




这道题就是求一个集合的第\(k\)小亦或和。




首先线性基的概念、构造方法什么的看上面的blog就好啦。

这里补充一点,只有求第\(k\)小(大)的亦或和的时候才用把每一位独立开来,即必须满足\(p[i] = 2 ^i\)。其他的操作(比如亦或最大值)就不用了。




那么现在我们已经得到了线性基,且满足如果\(p[i]\)存在,就有\(p[i] = 2 ^ i\)。

首先,对于不存在的\(p[i]\),要把他踢出去,因为这一位在计算答案的时候是没有贡献的。

然后如果求第\(k\)小,就把\(p[i]\)从低位到高位存到另一个数组中(去0位);如果是第\(k\)大,就应该从高位到低位存下来。

那么对于\(k\),转换成二进制,如果第\(i\)位为\(0\),就把答案亦或上\(p[i]\)。

大体的流程就是这样。

接下来说一下细节:

1.如果线性基大小小于\(n\),就说明有的数能被其他数亦或得到,也就是说,答案是包含\(0\)的。这时候就要把\(k\)减1。

2.无解条件是\(k > 2^cnt - 1\)。之所以减1,是因为虽然有\(2 ^ cnt\)种可能,但是0是不算的,因此只有\(2 ^cnt - 1\)个数。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxN = 63;
inline ll read()
{
ll ans = 0;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) {last = ch; ch = getchar();}
while(isdigit(ch)) {ans = (ans << 1) + (ans << 3) + ch - '0'; ch = getchar();}
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < 0) x = -x, putchar('-');
if(x >= 10) write(x / 10);
putchar(x % 10 + '0');
} int n, m;
ll p[maxN + 5];
In void insert(ll x)
{
for(int i = maxN; i >= 0; --i)
{
if((x >> (ll)i) & 1)
{
if(p[i]) x ^= p[i];
else
{
for(int j = i - 1; j >= 0; --j) if((x >> j) & 1) x ^= p[j];
for(int j = maxN; j > i; --j) if((p[j] >> i) & 1) p[j] ^= x;
p[i] = x; return;
}
}
}
}
ll b[maxN + 5], cnt = 0;
In void change() //第k小,正着存
{
for(int i = 0; i <= maxN; ++i) if(p[i]) b[cnt++] = p[i];
}
In ll query(ll k)
{
if(cnt < n) --k;
if(k > (1LL << cnt) - 1) return -1;
ll ret = 0;
for(int i = 0; i < cnt; ++i)
{
if((k >> i) & 1) ret ^= b[i];
}
return ret;
}
In void init()
{
Mem(p, 0); Mem(b, 0); cnt = 0;
} int main()
{
int T = read(), cntT = 0;;
while(T--)
{
printf("Case #%d:\n", ++cntT);
init();
n = read(); ll x;
for(int i = 1; i <= n; ++i) x = read(), insert(x);
change();
m = read();
for(int i = 1; i <= m; ++i) x = read(), write(query(x)), enter;
}
return 0;
}

HDU3949 XOR的更多相关文章

  1. HDU3949 XOR (线性基)

    HDU3949 XOR Problem Description XOR is a kind of bit operator, we define that as follow: for two bin ...

  2. hdu3949 XOR xor高斯消元

    XOR Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...

  3. 【线性基】hdu3949 XOR

    给你n个数,问你将它们取任意多个异或起来以后,所能得到的第K小值? 求出线性基来以后,化成简化线性基,然后把K二进制拆分,第i位是1就取上第i小的简化线性基即可.注意:倘若原本的n个数两两线性无关,也 ...

  4. [hdu3949]XOR(线性基求xor第k小)

    题目大意:求xor所有值的第k小,线性基模板题. #include<cstdio> #include<cstring> #include<algorithm> #i ...

  5. HDU3949 XOR(线性基第k小)

    Problem Description XOR is a kind of bit operator, we define that as follow: for two binary base num ...

  6. HDU3949:XOR(高斯消元)(线性基)

    传送门 题意 给出n个数,任意个数任意数异或构成一个集合,询问第k大个数 分析 这题需要用到线性基,下面是一些资料 1.高斯消元&线性基&Matirx_Tree定理 笔记 2.关于线性 ...

  7. 【HDU3949】XOR

    [题目大意] 给定一个数组,求这些数组通过异或能得到的数中的第k小是多少. 传送门:http://vjudge.net/problem/HDU-3949 [题解] 首先高斯消元求出线性基,然后将k按照 ...

  8. HDU3949:XOR——题解

    http://acm.hdu.edu.cn/showproblem.php?pid=3949 求n个数的异或和第k小. 参考:https://blog.sengxian.com/algorithms/ ...

  9. HDU3949/AcWing210 XOR (高斯消元求线性基)

    求第k小的异或和,用高斯消元求更简单一些. 1 //用高斯消元求线性基 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define ...

随机推荐

  1. HTML5 audio元素如何使用js与jquery控制其事件

    前言: 每一次遇见问题想到的就是怎么解决?最好的方法还是查询网络媒体,更好的办法是让自己记忆,只有自己理解到了才真正是属于自己.要做一个订单提醒功能,没有使用audio相关的插件,虽然插件无数,还是喜 ...

  2. gulp报错task function must be specified

    1.我npm安装了Browserify,tsify和vinyl-source-stream包,想要引用安装的插件,所以就走了引用插件的流程,修改了gulpfiles.js文件,引用流程完毕后,在终端g ...

  3. 记一次安装Nginx+php-fpm安装后无法解析.php文件,状态码200,但显示空白页

    安装环境: Nginx:Nginx1.12.2 PHP:PHP 7.2 系统:CentOS 7.4 安装方式: Nginx与PHP都是yum安装的,具体步骤: 1.安装epel源再安装Nginx: r ...

  4. 13.Linux键盘按键驱动 (详解)

    在上一节分析输入子系统内的intput_handler软件处理部分后,接下来我们开始写input_dev驱动 本节目标: 实现键盘驱动,让开发板的4个按键代表键盘中的L.S.空格键.回车键 1.先来介 ...

  5. Java8的lambda表达式和Stream API

    一直在用JDK8 ,却从未用过Stream,为了对数组或集合进行一些排序.过滤或数据处理,只会写for循环或者foreach,这就是我曾经的一个写照. 刚开始写写是打基础,但写的多了,各种乏味,非过来 ...

  6. STOMP

    STOMP: 说明:STOMP is a simple text-orientated messaging protocol. 面向文本消息协议 spring 之stomp https://www.c ...

  7. JavaScript基础要点

    一.值和类型及运算 JavaScript中的六种基本值类型 数字(number).字符串(string).布尔值(boolean).对象(object).函数(function).未定义类型(unde ...

  8. csharp: Use of Is and As operators in csharp

    /// <summary> /// Geovin Du 20170622 /// </summary> /// <param name="sender" ...

  9. git 查看/修改用户名、密码

    用户名和邮箱地址的作用 用户名和邮箱地址是本地git客户端的一个变量,不随git库而改变. 每次commit都会用用户名和邮箱纪录. github的contributions统计就是按邮箱来统计的. ...

  10. Linux常用系统命令

    致歉:各位看到此博客的朋友们 因为命令的数量挺多的很多命令也都很简单  我就总结了一下具体的命令和这个命令是做什么的,主要的使用方法是链接到http://man.linuxde.net/的网站的,请各 ...