[HDU3949]XOR

題目

傳送門 to HDU

傳送門 to VJ

題目概要
對於 a1,a2,a3,,ana_1,a_2,a_3,\dots,a_n ,記 S={xx=at1at2at3atkr}S=\{x|x=a_{t_1}\oplus a_{t_2}\oplus a_{t_3}\oplus\cdots\oplus a_{t_kr}\} ,求 SS 中第 kk 大的元素。

思路

其實就是板題 😅 求一個線性基,然後處理一下就好了。

有一個細節,讓 ansdi>ansans\oplus d_i > ans ,然後進行抉擇,類似於權值線段樹的操作。

代碼

#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
typedef long long int_;
inline int_ readint(){
	int_ x; scanf("%lld",&x); return x;
}

int_ d[100]; int cnt;
void insert(int_ x){
	for(int i=63; i>=0&&x; --i){
		if((x>>i&1) == 0) continue;
		if(d[i] != 0) x ^= d[i];
		else {
			d[i] = x, ++ cnt; break;
		}
	}
}

int main(){
	int kase = 0;
	for(int T=readint(); T; --T){
		int n = readint();
		for(int i=0; i<64; ++i) d[i] = 0;
		for(int i=cnt=0; i<n; ++i)
			insert(readint());
		printf("Case #%d:\n",++kase);
		for(int q=readint(); q; --q){
			int_ k = readint(), ans = 0;
			if(k == 1 and cnt < n){
				puts("0"); continue;
			}
			int now = cnt; k -= (cnt < n);
			for(int i=63; i>=0; --i){
				if(d[i] == 0) continue;
				if(ans>>i&1) ans ^= d[i];
				int_ f = (1ll<<(now-1));
				if(ans == 0) // 一個都沒選
					-- f; // 去掉全都不選的方案
				if(k > f)
					k -= f, ans ^= d[i];
				-- now; // 去掉這個抉擇
			}
			if(k > 1) puts("-1");
			else printf("%lld\n",ans);
		}
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章