[hdu3949][高斯消元][线性基]XOR

5 篇文章 0 订阅

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.

翻译

T组数据
每组数据给出n个数,从中选出几个数进行异或运算,多次询问第k小的数是多少

题解

线性基的另一种求法
我们知道高斯消元进行的实际上也是基础行变换,消元后得到的异或空间是不会变的
于是我们可以直接对这n个数的二进制拆分后高斯消元解异或方程组
由高斯消元的性质可以知道对于第(i,i)个主元,在第i列有且仅有(i,i)的值为1
抽象回这些数我们可以发现每个数分别代表了一个二进制位,即异或时必须要异或这些数才能得到这个二进制位的贡献
对k进行二进制拆分。我们可以发现,对于k的二进制最低位,如果为1,我们即异或高斯消元后排在最后的数,倒数第二位为1时我们异或倒数第二个数,以此类推。手玩一下可以玩出结论
对于0的情况要进行特判,判断高斯消元后是否存在空行即是否能通过异或方程得到0

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
int n,m;
LL f[11000];
int p[70];
int main()
{
    int T;scanf("%d",&T);
    for(int tt=1;tt<=T;tt++)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%lld",&f[i]);
        for(int i=1;i<=n;i++)
        {
            for(int j=i+1;j<=n;j++)if(f[i]<f[j])swap(f[i],f[j]);
            if(f[i]==0)break;
            for(int k=62;k>=0;k--)
            {
                if(f[i]&(1LL<<k))
                {
                    for(int j=1;j<=n;j++)if(f[j]&(1LL<<k) && j!=i)f[j]=f[j]^f[i];
                    break;
                }
            }
        }
        int sum=0;
        bool bk=false;
        for(int i=1;i<=n;i++)
        {
            if(!f[i])bk=true;
            else sum++;
        }
        printf("Case #%d:\n",tt);
        scanf("%d",&m);
        while(m--)
        {
            LL num;scanf("%lld",&num);
            if(bk)num--;
            memset(p,0,sizeof(p));int ln=0;
            while(num)p[++ln]=num%2,num>>=1;
            if(ln>sum){printf("-1\n");continue;}
            LL ans=0;int last=sum;
            for(int i=1;i<=ln;i++,last--)if(p[i]==1)ans^=f[last];
            printf("%lld\n",ans);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值