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 }
深深地明白自己的弱小