【HDU 3949】 XOR (线性基,高斯消元)
XOR
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2302 Accepted Submission(s): 783Problem DescriptionXOR is a kind of bit operator, we define that as follow: for two binary base number A and B, let C=A XOR B, then for each bit of C, we can get its value by check the digit of corresponding position in A and B. And for each digit, 1 XOR 1 = 0, 1 XOR 0 = 1, 0 XOR 1 = 1, 0 XOR 0 = 0. And we simply write this operator as ^, like 3 ^ 1 = 2,4 ^ 3 = 7. XOR is an amazing operator and this is a question about XOR. We can choose several numbers and do XOR operatorion to them one by one, then we get another number. For example, if we choose 2,3 and 4, we can get 2^3^4=5. Now, you are given N numbers, and you can choose some of them(even a single number) to do XOR on them, and you can get many different numbers. Now I want you tell me which number is the K-th smallest number among them.InputFirst line of the input is a single integer T(T<=30), indicates there are T test cases.
For each test case, the first line is an integer N(1<=N<=10000), the number of numbers below. The second line contains N integers (each number is between 1 and 10^18). The third line is a number Q(1<=Q<=10000), the number of queries. The fourth line contains Q numbers(each number is between 1 and 10^18) K1,K2,......KQ.OutputFor each test case,first output Case #C: in a single line,C means the number of the test case which is from 1 to T. Then for each query, you should output a single line contains the Ki-th smallest number in them, if there are less than Ki different numbers, output -1.Sample Input2
2
1 2
4
1 2 3 4
3
1 2 3
5
1 2 3 4 5Sample OutputCase #1:
1
2
3
-1
Case #2:
0
1
2
3
-1HintIf you choose a single number, the result you get is the number you choose.
Using long long instead of int because of the result may exceed 2^31-1.
求线性基?好像很厉害的东西..
证明的话应该要用到X^Y=Z -> X^Z=Y这个性质
线性基的相互异或的值可以完全代替原来的n个数的异或的值,这样数从n个变成了二进制位数个,数减少了很多这是一个优点。
另外,像高斯消元一样求线性基的话,如果某一位上有代表这一位的1,那么其他位置上一定为0。(这个性质好像很好用,因为这样可以看作这个数是对这一位作唯一贡献的,这样求很多东西都很方便了) 所以感觉异或版的高斯消元跟普通的高斯消还是很不一样的,多了好性质啊..
放一下让我看懂的解释吧~
1、线性基:
若干数的线性基是一组数a1,a2,...an,其中ax的最高位的1在第x位。通过线性基中元素xor出的数的值域与原来的数xor出数的值域相同。
2、线性基的构造法:
对每一个数p从高位到低位扫,扫到第x位为1时,若ax不存在,则ax=p并结束此数的扫描,否则令p=p xor ax。
3、查询:
用线性基求这组数xor出的最大值:从高往低扫ax,若异或上ax使答案变大,则异或。
4、判断:
用线性基求一个数能否被xor出:从高到低,对该数每个是1的位置x,将这个数异或上ax(注意异或后这个数为1的位置和原数就不一样了),若最终变为0,则可被异或出。需要特判0(在构造过程中看是否有p变为0即可)。例子:(11111,10001)的线性基是a5=11111,a4=01110,要判断11111能否被xor出,11111 xor a5=0,则这个数后来就没有是1的位置了,最终得到结果为0,说明11111能被xor出。
个人谈一谈对线性基的理解:
很多情况下,只有有关异或运算和求最值,就可以用到线性 基。线性基有很多很好的性质,比如说如果有很多个数,我们可以构出这些数的线性基,那么这个线性基可以通过互相xor,能够构出原来的数可以相互xor构出的所有的数。所以可以大大减少判断的时间和次数。同时线性基的任何一个非空子集都不会使得其xor和为0,证明也很简单,反证法就可以说明。这个性质在很多题目中可以保证算法合法性,比如:BZOJ2460。
构造的方法有点像贪心,从大到小保证高位更大。也比较好理解。就是这几行代码:
for(int i=1;i<=n;i++) {
for(int j=62;j>=0;j--) {
if(!(a[i]>>j)) continue;//对线性基的这一位没有贡献
if(!p[j]) { p[j]=a[i]; break; }//选入线性基中
a[i]^=p[j];
}
}
可以把n个数变成只有二进制位数那么多的数,这就是线性基的优秀之处。
查询的话,也是一个贪心思想,如果可以使得ans更大,就把这一位的基xor进ans。
for(int i=62;i>=0;i--) if((ans^p[i])>ans) ans=ans^p[i];//从线性基中得到最大值
这就是线性基的基本用法和个人的一些理解。
代码如下:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cmath>
using namespace std;
#define Maxn 10010
#define LL long long LL a[Maxn],num[];
int n,cnt; void gauss()
{
int l=,r=;
LL t;
while(l<=n&&r>=)
{
if(!(a[l]&(1LL<<r-)))
{
for(int i=l+;i<=n;i++) if(a[i]&(1LL<<r-))
{
t=a[l],a[l]=a[i],a[i]=t;
break;
}
}
if(!(a[l]&(1LL<<r-)))
{
r--;continue;
}
num[r]=l;
for(int i=;i<=n;i++) if(i!=l&&(a[i]&(1LL<<r-))) a[i]^=a[l];
l++;r--;
}
} void init()
{
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%lld",&a[i]);
memset(num,,sizeof(num));
gauss();
for(int i=;i<=;i++) if(num[i]!=) num[i]=a[num[i]];
cnt=;
for(int i=;i<=;i++) if(num[i]!=) cnt++;
} int main()
{
int T,kase=;
scanf("%d",&T);
while(T--)
{
init();
printf("Case #%d:\n",++kase);
int q;
scanf("%d",&q);
while(q--)
{
LL k;
scanf("%lld",&k);
if(cnt==n) k++;//zero
if(k>(1LL<<cnt)) {printf("-1\n");continue;}
int now=cnt;
LL ans=;
for(int i=;i>=;i--) if(num[i]!=)
{
LL x=(1LL<<now-);
if(k>x) ans^=num[i],k-=x;
now--;
}
printf("%lld\n",ans);
}
}
return ;
}
[HDU3969]
2016-09-30 15:03:05
【HDU 3949】 XOR (线性基,高斯消元)的更多相关文章
- HDU 3949 XOR [线性基|高斯消元]
目录 题目链接 题解 代码 题目链接 HDU 3949 XOR 题解 hdu3949XOR 搞死消元找到一组线性无关组 消出对角矩阵后 对于k二进制拆分 对于每列只有有一个1的,显然可以用k的二进制数 ...
- HDU 3949 XOR ——线形基 高斯消元
[题目分析] 异或空间的K小值. 高斯消元和动态维护线形基两种方法都试了试. 动态维护更好些,也更快(QAQ,我要高斯消元有何用) 高斯消元可以用来开拓视野. 注意0和-1的情况 [代码] 高斯消元 ...
- [bzoj 2844]线性基+高斯消元
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2844 又用到线性基+高斯消元的套路题了,因为经过高斯消元以后的线性基有非常好的序关系,所以 ...
- [hdu 3949]线性基+高斯消元
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3949 一开始给做出来的线性基wa了很久,最后加了一步高斯消元就过了. 之所以可以这样做,证明如下. 首 ...
- Codeforces.472F.Design Tutorial: Change the Goal(构造 线性基 高斯消元)
题目链接 \(Description\) 给定两个长为\(n\)的数组\(x_i,y_i\).每次你可以选定\(i,j\),令\(x_i=x_i\ \mathbb{xor}\ x_j\)(\(i,j\ ...
- 【题解】 bzoj1923: [Sdoi2010]外星千足虫 (线性基/高斯消元)
bzoj1923,戳我戳我 Solution: 这个高斯消元/线性基很好看出来,主要是判断在第K 次统计结束后就可以确定唯一解的地方和\(bitset\)的骚操作 (我用的线性基)判断位置,我们可以每 ...
- 洛谷P3265 [JLOI2015]装备购买(线性基+高斯消元)
传送门 不知道线性基是什么东西的可以看看蒟蒻的总结 不难看出题目讲的就是线性基 这种最小化权值的问题一般都是贪心的,就是按价值从低到高考虑每一个是否能选 据说贪心的证明得用拟阵我不会 据说这题是实数意 ...
- 【bzoj4004】【JLOI2015】装备购买 (线性基+高斯消元)
Description 脸哥最近在玩一款神奇的游戏,这个游戏里有 n 件装备,每件装备有 m 个属性,用向量zi(aj ,.....,am) 表示 (1 <= i <= n; 1 < ...
- hdu 3949 XOR (线性基)
链接: http://acm.hdu.edu.cn/showproblem.php?pid=3949 题意: 给出n个数,从中任意取几个数字异或,求第k小的异或和 思路: 线性基求第k小异或和,因为题 ...
- HDU 3949 XOR 线性基
http://acm.hdu.edu.cn/showproblem.php?pid=3949 求异或第k小,结论是第k小就是 k二进制的第i位为1就把i位的线性基异或上去. 但是这道题和上一道线性基不 ...
随机推荐
- Socket.io 0.7 – Sending messages to individual clients
Note that this is just for Socket.io version 0.7, and possibly higher if they don’t change the API a ...
- C# ADO.NET参数查询
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- JQuery设置缓慢下拉大行多次执行的解决办法,以及stop()函数的简单理解
$(function(){ $('.all>li').mouseover(function(e) { $(this).children().stop().slideDown(300 ...
- [转]SharePoint 2010/2013 使用Javascript来判断权限的三种方法
本文讲述SharePoint 2010/2013 使用Javascript来判断权限的三种方法的实现方式及其优缺点. 1. 根据用户所在的SharePoint组(比如用户在Leader 组才可以使用审 ...
- bootstrap--组件之按钮式下拉菜单
把任意一个按钮放入 .btn-group 中,然后加入适当的菜单标签,就可以让按钮作为菜单的触发器了. 简单的实现如下 Code<div class="btn-group"& ...
- Linux的各种命令(android adb shell)
win+r 调出运行,输入CMD adb shell 进入手机的控制终端,相当于原生的Linux系统的各种操作. 当提示符为$符号,说明未获得超级管理员权限,输入su,可编程# adb kill-se ...
- 【SQL】Update中使用表别名、如何用表中一列值替换另一列的所有值
Update中使用表别名 select中的表别名: select * from TableA as ta update中的表别名: update ta from TableA as ta 如何用表中一 ...
- 实现输出h264直播流的rtmp服务器 flash直播服务器
http://www.cnblogs.com/haibindev/archive/2012/04/16/2450989.html 实现输出h264直播流的rtmp服务器 RTMP(Real Time ...
- 使用RPC 调用NameNode中的方法
用户在Client 端是很难对 NameNode中的信息进行直接访问的, 所以 ,在Hadoop系统中为 Client端 提供了一系列的方法调用,这些方法调用是通过RPC 方法来实现的, 根据RPC ...
- 转载:为什么Linux不需要磁盘碎片整理
转载自:www.aqee.net 如果你是个Linux用户,你可能听说过不需要去对你的linux文件系统进行磁盘碎片整理.也许你注意到了,在Liunx安装发布包里没有磁盘碎片整理的工具.为什么会这样? ...