HDU 3949 XOR ——线形基 高斯消元
【题目分析】
异或空间的K小值。
高斯消元和动态维护线形基两种方法都试了试。
动态维护更好些,也更快(QAQ,我要高斯消元有何用)
高斯消元可以用来开拓视野。
注意0和-1的情况
【代码】
高斯消元
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 10005 #define ll long long #define F(i,j,k) for (ll i=j;i<=k;++i) #define D(i,j,k) for (ll i=j;i>=k;--i) void Finout() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); #endif } inline ll read() { ll x=0;char ch=getchar(); while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x; } int T,n,m,tot,zero; ll bin[65],a[maxn]; void gauss() { tot=zero=0; for (ll i=bin[60];i;i>>=1) { int j=tot+1; while (!(i&a[j])&&j<=n) j++; if (j==n+1) continue; tot++; swap(a[tot],a[j]); F(k,1,n) if (k!=tot&&(a[k]&i)) a[k]^=a[tot]; } if (tot!=n) zero=1; } ll query(ll x) { ll sum=0; x-=zero; if (!x) return 0; if (x>=bin[tot]) return -1; F(i,1,tot) if (x&bin[tot-i]) sum^=a[i]; return sum; } int main() { Finout(); bin[0]=1;F(i,1,60) bin[i]=bin[i-1]<<1; T=read(); F(z,1,T) { memset(a,0,sizeof a); printf("Case #%d:\n",z); n=read(); F(i,1,n) a[i]=read(); gauss(); m=read(); while (m--) { int x=read(); printf("%lld\n",query(x)); } } }
动态维护线形基
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define ll long long #define F(i,j,k) for (ll i=j;i<=k;++i) #define D(i,j,k) for (ll i=j;i>=k;--i) void Finout() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); #endif } ll Getll() { ll x=0; char ch=getchar(); while (ch<'0'||ch>'9') ch=getchar(); while (ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x; } ll T,Q,n,x,tab,kas=0;; ll a[10001],lb[70],rk; bool cmp(ll x,ll y) {return x>y;} bool cmp2(ll x,ll y) {return x<y;} int main() { scanf("%lld",&T); while (T--) { printf("Case #%lld:\n",++kas); tab=1; ll flag=0,cnt=0; memset(lb,0,sizeof lb); scanf("%lld",&n); F(i,1,n) scanf("%lld",&a[i]); F(i,1,n) { D(j,63,0) if ((a[i]>>j)&1){ if (lb[j]) a[i]^=lb[j]; else { cnt++; lb[j]=a[i]; F(k,0,62) F(r,k+1,63) if ((lb[r]>>k)&1) lb[r]^=lb[k]; break; } } if (!a[i]) flag=1; } cnt=0; for (int i=0;i<=63;++i) { if (lb[i]) lb[cnt++]=lb[i]; } scanf("%lld",&Q); F(i,1,Q) { scanf("%lld",&rk); rk-=flag; ll sum=0; if (rk>>cnt) printf("-1\n"); else { F(j,0,cnt-1) if ((rk>>j)&1) sum^=lb[j]; printf("%lld\n",sum); } } } }