1. 程式人生 > >2018.12.07【LOJ114】k 大異或和(線性基)(高斯消元)

2018.12.07【LOJ114】k 大異或和(線性基)(高斯消元)

傳送門


解析:

先求一個線性基,然後高斯消元解線性空間,然後基本上就是亂搞把第 k k 大湊出來就行了。


程式碼:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc get_char
#define pc put_char
#define cs const namespace IO{ cs int Rlen=1<<18|1; char buf[Rlen],*p1,*p2; char obuf[Rlen],*p3=obuf,*p4=obuf+Rlen; inline char get_char(){ return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++; } inline ll getint(){ re ll num; re char c; while(!isdigit
(c=gc()));num=c^48; while(isdigit(c=gc()))num=num*10+(c^48); return num; } inline void put_char(cs char &c){ *p3++=c; if(p3==p4)fwrite(obuf,1,Rlen,stdout),p3=obuf; } inline void outint(ll a){ static char ch[23]; if(a==0)pc('0'); if(a<0)pc('-'),a=-a; while(a)ch[++ch[0]]=a-a/10
*10,a/=10; while(ch[0])pc(ch[ch[0]--]^48); } inline void FLUSH(){ if(p3==obuf)return ; fwrite(obuf,1,p3-obuf,stdout); p3=obuf; } } using namespace IO; int n,m; ll b[51]; ll num[51],cnt; int main(){ n=getint(); for(int re i=1;i<=n;++i){ re ll u=getint(); for(int re i=50;~i;--i) if(u&(1ll<<i)){ if(!b[i]){ b[i]=u; break; } else u^=b[i]; } } for(int re i=1;i<=50;++i) for(int re j=0;j<i;++j){ if((1ll<<j)&b[i]) b[i]^=b[j]; } for(int re i=0;i<=50;++i) if(b[i])num[cnt++]=b[i]; m=getint(); while(m--){ re ll k=getint(); if(cnt!=n)--k; if(k>=(1ll<<cnt)){ outint(-1);pc('\n'); continue; } re ll res=0; for(int re i=0;i<=50;++i){ if(k&(1ll<<i)) res^=num[i]; } outint(res); pc('\n'); } FLUSH(); return 0; }