題目描述數組
給由 $n$ 個數組成的一個可重集 $S$ ,每次給定一個數 $k$ ,求一個集合 $T⊆S$ ,使得集合 $T$ 在 $S$ 的全部非空子集的不一樣的異或和中,其異或和 $T_1\ \text{xor}\ T_2\ \text{xor}\ …\ \text{xor}\ T_{|T|}$ 是第 $k$ 小的。求這個第 $k$ 小的異或和。spa
題解blog
線性基+特判get
板子題沒什麼好說的,直接求出嚴格線性基,因爲每一個最高位只有一個所以按位判斷便可。it
關鍵在於一個特判:原來的可重集可能可以組成0,也可能不可以組成0,須要判斷一下0是否算在內。io
時間複雜度 $O(n\log n)$ class
#include <cstdio> #include <algorithm> using namespace std; typedef long long ll; ll a[100010] , tot; int main() { int n , m , i , flag = 0; ll j , ans; scanf("%d" , &n); for(i = 1 ; i <= n ; i ++ ) { scanf("%lld" , &a[i]); if(a[i] == 0) flag = 1; } for(j = 1ll << 49 ; j ; j >>= 1) { for(i = tot + 1 ; i <= n ; i ++ ) if(a[i] & j) break; if(i > n) continue; swap(a[i] , a[++tot]); for(i = 1 ; i <= n ; i ++ ) if(i != tot && a[i] & j) a[i] ^= a[tot]; } for(i = 1 ; i <= n ; i ++ ) if(a[i] == 0) flag = 1; scanf("%d" , &m); while(m -- ) { scanf("%lld" , &j) , j -= flag; if(j >= 1ll << tot) puts("-1"); else { ans = 0; for(i = 1 ; i <= tot ; i ++ ) if(j & (1ll << (tot - i))) ans ^= a[i]; printf("%lld\n" , ans); } } return 0; }