線性基模板題hdu3949
阿新 • • 發佈:2019-01-30
hdu3949 XOR
題目大意:
就是給你長度為N的學列,有Q次查詢,每次查詢這寫序列中能異或出來的第k小的值
解題思路 :
本題是一個線性基的入門題。
其實線性基的求解過程就是一個高斯消元,它構建了一個二維的空間,N*bits這麼大,
通過列與列相消,求解出基向量也就是空間的極大無關組,通過這幾個元素能得到含蓋空間中所有元素的無關組.
本題求的就是這個無關組能構建出來的第K小的值.
求這個值我們可以類比最理想情況下的無關組,
1 0 0 0 0 0 … 0 p1
0 1 0 0 0 0 … 0 p2
…
0 0 0 0 0 0 … 0 pn
那麼對於第K小的值就是將K二進位制展開,第i位上為1,就在結果上異或
程式碼:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; int n,m; unsigned long long a[10005],ins[100]; bool flag; void EX_Ins(int n) { int i,j,k; flag=0; memset(ins,0,sizeof ins); for(i=n;i;i--) { for(j=63;~j;j--)if((a[i]>>j)&1) { if(!ins[j]) { ins[j]=a[i]; for(k=0;k<63;k++) for(int r=k+1;r<=63;r++) if((ins[r]>>k)&1) ins[r]^=ins[k]; break; } else a[i]^=ins[j]; } if(!a[i])flag=1; } return ; } int main() { //freopen("test.in","r",stdin); int i,g,_g; unsigned long long k; for(scanf("%d",&_g),g=1;g<=_g;g++) { printf("Case #%d:\n",g); scanf("%d",&n); for(i=1;i<=n;i++)scanf("%llu",&a[i]); //下面四行完成線性基的操作 EX_Ins(n); for(m=i=0;i<=63;i++) { if(ins[i])ins[m++]=ins[i]; } // for(i=0;i<=m-1;i++) // cout<<ins[i]<<endl; for(scanf("%d",&n);n--;) { scanf("%llu",&k); if(flag)k--; //flag是1,說明有0 if(k>>m)puts("-1");//共能組成2的M次方個,如果k更大,那就impossible else { unsigned long long ret=0; for(i=0;i<m;i++)//(原理是從低位開始一位一位異或上去) if((k>>i)&1) ret^=ins[i]; printf("%llu\n",ret); } } } return 0; }