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

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3949

XOR

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

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.

Author

elfness

Source

2011 Multi-University Training Contest 11 - Host by UESTC

Recommend

xubiao   |   We have carefully selected several similar problems for you:  3946 3948 3947 3945 3944

题目大意:输入t,t组样例,输入n,有n个数,接下来为n个数的值,输入q,代表q次询问,接下来q个数,要你求出第k小的数

学习:https://www.cnblogs.com/vb4896/p/6149022.html

思路:这一题显然是线性基来做,首先先把最大线性无关组,也就是线性基求出来,然后题目要求是要你求出第k小的数,在线性基的基础上,我们可以稍微改造一下,就是保证只有b[i]的第i位是1,其它的第i

位都为0,有了这个性质,我们要求第k小的数,就是把k用二进制表示,如果第j为是1的话,就异或第j个线性基的向量,这里可能需要的读者多想一下,(因为都是二进制表示,具体的我也描述不出来)

看代码:

#include<iostream>
#include<string.h>
#include<map>
#include<cstdio>
#include<cstring>
#include<stdio.h>
#include<cmath>
#include<ctype.h>
#include<math.h>
#include<algorithm>
#include<set>
#include<queue>
typedef long long ll;
using namespace std;
const ll mod=1e9+7;
const int maxn=1e4+10;
const int maxk=5e3+10;
const int maxx=1e4+10;
const ll maxe=1000+10;
#define INF 0x3f3f3f3f3f3f
#define Lson l,mid,rt<<1
#define Rson mid+1,r,rt<<1|1
ll a[maxn],b[100];
ll m,k;
void guass(int n)
{
    memset(b,0,sizeof(b));
    for(int i=0;i<n;i++)
    {
        for(int j=63;j>=0;j--)
        {
            if((a[i]>>j)&1)
            {
                if(!b[j])
                {
                    b[j]=a[i];
                    break;
                }
                else
                {
                    a[i]^=b[j];
                }
            }
        }
    }
    for(int i=63;i>=0;i--)
    {
        if(!b[i]) continue;
        for(int j=i+1;j<=63;j++)
        {
            if((b[j]>>i)&1) b[j]^=b[i];//为了使得只有b[i]的第i为1,其它的都不为1
        }
    }
    m=0;
    for(int i=0;i<=63;i++) if(b[i]) b[m++]=b[i];
}
int main()
{
    int t,ca=1,n,q;
    cin>>t;
    while(t--)
    {
        cin>>n;
        printf("Case #%d:\n",ca++);
        for(int i=0;i<n;i++)
        {
            cin>>a[i];
        }
        guass(n);
        cin>>q;
        while(q--)
        {
            ll ans=0;
            cin>>k;
            if(n!=m) k--;//代表可以是0
            if(k>=(1ll<<m)) cout<<"-1"<<endl;
            else
            {
                for(int i=0;i<=63;i++) if((k>>i)&1) ans^=b[i];
                cout<<ans<<endl;
            }
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/caijiaming/p/9637189.html

时间: 2024-08-29 15:05:38

hdu3949(线性基,求第k小的异或和的相关文章

算法导论学习之线性时间求第k小元素+堆思想求前k大元素

对于曾经,假设要我求第k小元素.或者是求前k大元素,我可能会将元素先排序,然后就直接求出来了,可是如今有了更好的思路. 一.线性时间内求第k小元素 这个算法又是一个基于分治思想的算法. 其详细的分治思路例如以下: 1.分解:将A[p,r]分解成A[p,q-1]和A[q+1,r]两部分.使得A[p,q-1]都小于A[q],A[q+1,r]都不小于A[q]; 2.求解:假设A[q]恰好是第k小元素直接返回,假设第k小元素落在前半区间就到A[p,q-1]递归查找.否则到A[q+1,r]中递归查找. 3

STL--H - Black Box(两个优先队列,求第k小的值)

H - Black Box Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit Status Description Our Black Box represents a primitive database. It can save an integer array and has a special i variable. At the initial moment Black

Quick-Select 1亿个数快速求第K小的数 分治法

Quick-Select  1亿个数快速求第K小的数  分治法 利用快速排序的思想,一开始选取中枢元,然后左右调整,接着比对中枢元p和K的大小,如果 p+1 = k (数组从0开始), 那么a[p] 就是答案,因为在p之前的,肯定都是小于a[p]的, 在p之后的,肯定大于p, 所以 a[p] 就是第 p+1 小.假如 p+1 不等于K, 那么根据大小,进行左右调整.调整过程中,理想状态下,每次都砍掉一半,数组的起始坐标要进行调整. 代码: // 快速排序法的修改 #include <iostre

树状数组求第K小值 (spoj227 Ordering the Soldiers &amp;&amp; hdu2852 KiKi&#39;s K-Number)

题目:http://www.spoj.com/problems/ORDERS/ and http://acm.hdu.edu.cn/showproblem.php?pid=2852 题意:spoj227:告诉每个位置前面有多少个数比当前位置小,求出原序列.hdu2852:设计一个容器,支持几种操作:增加/删除元素,求容器中比a大的数中第k小的数是多少. 分析:两个题思路都是求数组里面的第K小的数.开始一直在找O(N*logN)的方法,后来发现O(N*logN*logN)也是可以过的...两步:和

【模板】线性基求交

线性基求交 struct lb{ ll p[63]; lb(){ memset(p,0,sizeof(p)); } void clear(){ memset(p,0,sizeof(p)); } void ins(ll x){ for(int i=60;i>=0;i--) if((x>>i)&1){ if(!p[i]){ p[i]=x; return; }else x^=p[i]; } } }; lb merge(lb a,lb b){ lb g=lb(),tmp=a; ll cu

Luogu P1923 求第k小的数

Luogu P1923 求第k小的数 一看这题,静态查询区间第$k$小的数,不就是可持久化线段树(主席树)的模板题吗?!(误) 直接把主席树的板子打上来?: #include<bits/stdc++.h> #define N 200010 #define mid ((l+r)>>1) using namespace std; int n,m,l,r,k,ans,id,siz; int a[N],b[N]; struct segmenttree { int ls,rs,sum,roo

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

题目大意:求xor所有值的第k小,线性基模板题. #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<iostream> #include<cmath> using namespace std; typedef long long ll; const int MAX_BASE=63; ll base[64],a[10006]

HDU3949 线性基模板

Ac链接 给定n个数,求子集异或和的第k大.\(n\le10^5,a_i\le10^9\). 第一步肯定是构造线性基.设线性基的基底数量为k,那么子集异或和本质不同的个数为\(2^k\)(如果有为0的情况).其实求第k大很简单,你把k拆分成2进制,对应基底从左到右的每一位,如果为1就异或上去就行了.不过我们需要分为两种情况,一个是存在异或和为0的情况,一个是不存在的.如果不存在异或和为0,需要把k+1. #include<bits/stdc++.h> #define ll long long

HDU 5008 求第k小子串

本题要求第k小的distinct子串,可以根据height数组,二分出这个第k小子串所在后缀的位置信息.由于题目要求子串起始下标尽可能小.所以再在rank数组中,二分出与当前后缀LCP大于等于所求子串长度的范围.通过RMQ求出这个范围中最小的sa. 1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <string> 5 #include <string