hdu3949XOR(线性基)

传送门

 

不知道线性基是什么东西的可以看看蒟蒻的总结

题目大意:求一堆数字能异或出的第$k$大的数是多少

线性基求第k大好珂怕……

据大佬们说就是把$k$给二进制拆分,如果$k$的第$i$位为1,那么$ans^=b[i]$

然后就是注意矩阵得消成对角矩阵而不是上三角矩阵……

这样的话$1$只会出现在对角线上

记$cnt$为对角线上有多少个$1$

显然能获得的异或值总共有$1<<cnt$个(包括0)

然后注意,如果$cnt!=n$,那么这一堆数字就是线性相关的,可以异或出0

否则的话说明这一堆数字线性无关,无法异或出0,那么得把$k++$(因为我们这里的$k$是默认能取到0的)

然后剩下的细节看代码好了

 1 //minamoto
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 #define ll long long
 6 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
 7 char buf[1<<21],*p1=buf,*p2=buf;
 8 inline ll read(){
 9     #define num ch-'0'
10     char ch;bool flag=0;ll res;
11     while(!isdigit(ch=getc()))
12     (ch=='-')&&(flag=true);
13     for(res=num;isdigit(ch=getc());res=res*10+num);
14     (flag)&&(res=-res);
15     #undef num
16     return res;
17 }
18 const int N=1e5+5;
19 int n,m,k;ll a[N],b[105];
20 void init(){
21     for(int i=1;i<=n;++i)
22     for(int j=63;j>=0;--j){
23         if(a[i]>>j&1){
24             if(b[j]) a[i]^=b[j];
25             else{
26                 b[j]=a[i];
27                 for(int k=j-1;k>=0;--k)
28                 if(b[k]&&(b[j]>>k&1)) b[j]^=b[k];
29                 for(int k=j+1;k<=63;++k)
30                 if(b[k]>>j&1) b[k]^=b[j];
31                 break;
32             }
33         }
34     }
35 }
36 int main(){
37 //    freopen("testdata.in","r",stdin);
38     int T=read();
39     for(int cas=1;cas<=T;++cas){
40         memset(b,0,sizeof(b));n=read();
41         for(int i=1;i<=n;++i) a[i]=read();
42         init();
43         int cnt=0;
44         for(int i=0;i<=63;++i)
45         if(b[i]) ++cnt;
46         m=read();
47         printf("Case #%d:\n",cas);
48         while(m--){
49             ll x=read();
50             if(cnt==n) ++x;
51             if(x>(1ll<<cnt)){puts("-1");continue;}
52             ll ans=0;
53             int tmp=cnt;
54             for(int i=63;i>=0;--i){
55                 if(b[i]){
56                     ll now=(1ll<<(tmp-1));
57                     if(x>now) x-=now,ans^=b[i];
58                     --tmp;
59                 }
60             }
61             printf("%lld\n",ans);
62         }
63     }
64     return 0;
65 }

 

posted @ 2018-09-27 19:03  bztMinamoto  阅读(160)  评论(0编辑  收藏  举报
Live2D