http://acm.hdu.edu.cn/showproblem.php?pid=3949
這題做過三次了,但是一直不是很懂,今天又理解了一下,就是讓你在n個數字裡面選一些,異或起來能得到一些值,然後問能得到的第k小的是多少。
這題首先每個數字都看成二進位,然後高斯消元,如果這一位是1,就把其他這一位是1的元素都異或它,消掉1,讓這一位的1隻有一個,然後得到一個k,就是說明消元完之後只有k個1,能夠組成 2k 2^k個數字,然後就是考慮這會的n個元素,每個元素都是原來的幾個數字異或得到的值,所以可以直接組合,考慮一些特殊情況,就是如果得到的k=n,那麼就是說每個數字都有1個1,那麼就絕對不可能取到0,那麼能夠組成的數字就是 2k−1 2^k-1個了,然後下面問你第k小,直接就是看k的二進位,哪一位有1,就把線性基裡面從小到大的那個1異或上去就行了。
代碼:
#include <map>#include <set>#include <stack>#include <queue>#include <cmath>#include <string>#include <vector>#include <cstdio>#include <cctype>#include <cstring>#include <sstream>#include <cstdlib>#include <iostream>#include <algorithm>#pragma comment(linker,"/STACK:102400000,102400000")using namespace std;#define MAX 10005#define MAXN 1000005#define maxnode 15#define sigma_size 30#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define lrt rt<<1#define rrt rt<<1|1#define middle int m=(r+l)>>1#define LL long long#define ull unsigned long long#define mem(x,v) memset(x,v,sizeof(x))#define lowbit(x) (x&-x)#define pii pair<int,int>#define bits(a) __builtin_popcount(a)#define mk make_pair#define limit 10000//const int prime = 999983;const int INF = 0x3f3f3f3f;const LL INFF = 0x3f3f;const double pi = acos(-1.0);const double inf = 1e18;const double eps = 1e-4;const LL mod = 1e9+7;const ull mx = 133333331;/*****************************************************/inline void RI(int &x) { char c; while((c=getchar())<'0' || c>'9'); x=c-'0'; while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0'; }/*****************************************************/LL a[MAX];int n;int gauss(){ int k=1; for(int i=63;i>=0;i--){ int t=0; for(int j=k;j<=n;j++){ if((a[j]>>i)&1){ t=j; break; } } if(t){ swap(a[k],a[t]); for(int j=1;j<=n;j++){ if(j!=k&&(a[j]>>i)&1) a[j]^=a[k]; } k++; } } return k-1;}int main(){ //freopen("in.txt","r",stdin); int t,kase=0; cin>>t; while(t--){ cin>>n; kase++; printf("Case #%d:\n",kase); for(int i=1;i<=n;i++) scanf("%I64d",&a[i]); int cnt=gauss(); LL tmp=(1LL<<cnt); if(cnt==n) tmp--; int k; cin>>k; while(k--){ LL x; scanf("%I64d",&x); if(x>tmp) printf("-1\n"); else{ if(n>cnt) x--; LL ans=0; for(int i=0;i<cnt;i++){ if((x>>i)&1) ans^=a[cnt-i]; } printf("%I64d\n",ans); } } } return 0;}