【線性基】HDU3949[XOR]題解
阿新 • • 發佈:2019-01-04
題目概述
給出 個數,求選出的非空集合中異或和第 小的異或和(異或和相同算一次),沒有 個輸出 。
解題報告
如果構造線性基時將矩陣消成對角矩陣,得到的線性基就有一個很棒的性質:最高位為 的數至多隻有一個,且其他數第 i 位為 (即使得到的線性基無法表示為對角矩陣,只要按照消成對角矩陣的方法去構造,也滿足這個性質)。
因為最高位為 的數至多隻有一個,所以挑出矩陣中的非零項 , 就是答案。
解題報告
#include<cstdio>
#include<cstring>
typedef long long LL;
using namespace std;
const int Log=60;
int te,n,Q;LL M[Log],B[Log];
inline void Insert(LL x){
for (int j=Log;~j;j--)
if (x>>j&1)
if (M[j]) x^=M[j]; else{
M[j]=x;for (int k=0;k<j;k++) if (M[j]>>k&1) M[j]^=M[k];
for (int k=j+1;k<Log;k++) if (M[k]>>j&1) M[k]^=M[j];break;
}
}
int main(){
freopen("program.in","r",stdin);
freopen("program.out","w",stdout);
for (int i=(scanf("%d",&te),1);i<=te;i++){
printf("Case #%d:\n",i);scanf("%d",&n);memset(M,0,sizeof(M));B[0 ]=0;
for (int i=1;i<=n;i++) {LL x;scanf("%lld",&x);Insert(x);}
for (int i=0;i<Log;i++) if (M[i]) B[++B[0]]=M[i];
for (scanf("%d",&Q);Q;Q--){
LL x,ans=0;int pos=0;scanf("%lld",&x);x-=B[0]<n;
while (x) {pos++;if (x&1) ans^=B[pos];x>>=1;}
if (B[0]<pos) puts("-1"); else printf("%lld\n",ans);
}
}
return 0;
}