XOR

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2302    Accepted Submission(s): 783

Problem Description
XOR 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.
Input
First 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.
Output
For 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 Input
2
2
1 2
4
1 2 3 4
3
1 2 3
5
1 2 3 4 5
Sample Output
Case #1:
1
2
3
-1
Case #2:
0
1
2
3
-1

Hint

If 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.

 
【题意】
  给n个数,可以在其中选任意个数异或,求所有异或出来的答案中的第k个。
 
【分析】
  

  求线性基?好像很厉害的东西..
  证明的话应该要用到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];//从线性基中得到最大值

  这就是线性基的基本用法和个人的一些理解。

转自:http://www.cnblogs.com/ljh2000-jump/p/5869991.html

代码如下:

 #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 (线性基,高斯消元)的更多相关文章

  1. HDU 3949 XOR [线性基|高斯消元]

    目录 题目链接 题解 代码 题目链接 HDU 3949 XOR 题解 hdu3949XOR 搞死消元找到一组线性无关组 消出对角矩阵后 对于k二进制拆分 对于每列只有有一个1的,显然可以用k的二进制数 ...

  2. HDU 3949 XOR ——线形基 高斯消元

    [题目分析] 异或空间的K小值. 高斯消元和动态维护线形基两种方法都试了试. 动态维护更好些,也更快(QAQ,我要高斯消元有何用) 高斯消元可以用来开拓视野. 注意0和-1的情况 [代码] 高斯消元 ...

  3. [bzoj 2844]线性基+高斯消元

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2844 又用到线性基+高斯消元的套路题了,因为经过高斯消元以后的线性基有非常好的序关系,所以 ...

  4. [hdu 3949]线性基+高斯消元

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3949 一开始给做出来的线性基wa了很久,最后加了一步高斯消元就过了. 之所以可以这样做,证明如下. 首 ...

  5. 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\ ...

  6. 【题解】 bzoj1923: [Sdoi2010]外星千足虫 (线性基/高斯消元)

    bzoj1923,戳我戳我 Solution: 这个高斯消元/线性基很好看出来,主要是判断在第K 次统计结束后就可以确定唯一解的地方和\(bitset\)的骚操作 (我用的线性基)判断位置,我们可以每 ...

  7. 洛谷P3265 [JLOI2015]装备购买(线性基+高斯消元)

    传送门 不知道线性基是什么东西的可以看看蒟蒻的总结 不难看出题目讲的就是线性基 这种最小化权值的问题一般都是贪心的,就是按价值从低到高考虑每一个是否能选 据说贪心的证明得用拟阵我不会 据说这题是实数意 ...

  8. 【bzoj4004】【JLOI2015】装备购买 (线性基+高斯消元)

    Description 脸哥最近在玩一款神奇的游戏,这个游戏里有 n 件装备,每件装备有 m 个属性,用向量zi(aj ,.....,am) 表示 (1 <= i <= n; 1 < ...

  9. hdu 3949 XOR (线性基)

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=3949 题意: 给出n个数,从中任意取几个数字异或,求第k小的异或和 思路: 线性基求第k小异或和,因为题 ...

  10. HDU 3949 XOR 线性基

    http://acm.hdu.edu.cn/showproblem.php?pid=3949 求异或第k小,结论是第k小就是 k二进制的第i位为1就把i位的线性基异或上去. 但是这道题和上一道线性基不 ...

随机推荐

  1. Magento强大的配置系统

    Magento的配置系统就像是Magento的心脏,支撑着Magento的运行.这套配置系统掌管着几乎所有"module/model/class/template/etc".它把整 ...

  2. ASP.NET MVC(三) TypeScript

    TypeScript 是微软开发的 JavaScript 的超集,TypeScript兼容JavaScript,可以载入JavaScript代码然后运行.TypeScript与JavaScript相比 ...

  3. DI(依赖注入)简单理解 NO1

    依赖注入:目的削减程序的耦合度,达到高内聚/低耦合 常用形式:Interface Driven Design接口驱动,接口驱动有很多好处,可以提供不同灵活的子类实现,增加代码稳定和健壮性等等.通过Io ...

  4. c语言学习之基础知识点介绍(二十):预处理指令

    一.预处理指令的介绍 预处理命令:在编译之前触发的一系列操作(命令)就叫预处理命令. 特点:以#开头,不要加分号. #include: 文件包含指令 把指定文件的内容复制到相应的位置 #define: ...

  5. ios Object Encoding and Decoding with NSSecureCoding Protocol

    Object Encoding and Decoding with NSSecureCoding Protocol February 27, 2014 MISC NSCoding is a fanta ...

  6. 理解RunLoop

    一.什么是RunLoop? 从字面意思上来看,RunLoop就是运行循环,跑圈的意思. 我们都知道,一般来说一个线程执行一次任务之后便会退出,在iOS中,如果主线程只执行一次便退出的话也就意味着程序的 ...

  7. 重新设置MySQL的root密码

    1.首先确认服务器出于安全的状态,也就是没有人能够任意地连接MySQL数据库. 因为在重新设置MySQL的root密码的期间,MySQL数据库完全出于没有密码保护的 状态下,其他的用户也可以任意地登录 ...

  8. c++动态绑定与静态绑定

    C++为了支持多态性,采用了动态绑定和静态绑定 相关概念: 对象的静态类型:对象在声明时采用的类型,编译时确定 对象的动态类型:目前所指对象的类型,在运行时确定 class B { } class C ...

  9. thinkphp 整合 ucenter

    http://xcodebox.com/2013/06/8855.html 参考 1   ucenter源码目录下 /advanced/examples/api目录 copy到thinkphp项目根目 ...

  10. apache虚拟主机安装注意事项

    apache虚拟主机在添加的时候,总是会有一些莫名其妙的问题,后来发现可以使用一个参数去验证的: xxxxx/httpd -S //这个参数会去检查虚拟主机配置的正确性,很好用 因为有时候可能就是缩进 ...