牛客练习赛26 D-xor序列(线性基)

题意:

小a有 (n) 个数,他提出了一个很有意思的问题:他想知道对于任意的 (x), (y),能否将 (x) 与这 (n) 个数中的任意多个数异或任意多次后变为 (y)

分析:

题目显然就是求:(x)(oplus)(a[i])(oplus)(a[j])(oplus)(a[k])(oplus)(...)(=y)
将这个式子移项得:(a[i])(oplus)(a[j])(oplus)(a[k])(oplus)(...)(=)(x)(oplus)(y)
所以就是在原序列的线性基判断是否能异或出 (x) (oplus) (y),即能否插入 (x)(oplus)(y) 的问题。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

const int N = 2e5 + 5;

struct Base {
	int tot, flag;
	LL d[66], nd[66];

	void init() {
		tot = flag = 0;
		memset(d, 0, sizeof d);
		memset(nd, 0, sizeof nd);
	}

	bool ins(LL x) {
		for (int i = 62; ~i; i--) {
			if (x & (1LL << i)) {
				if (d[i]) {
					x ^= d[i];
				} else {
					d[i] = x;
					return true;
				}
			}
		}
		flag = 1;
		return false;
	}
	
	bool canIns(LL x) {
		for (int i = 62; ~i; i--) {
			if (x & (1LL << i)) {
				if (d[i]) {
					x ^= d[i];
				} else {
					return true;
				}
			}
		}
		return false;
	}

	LL queryMax() {
		LL ans = 0;
		for (int i = 62; ~i; i--) ans = max(ans, ans ^ d[i]);
		return ans;
	}

	LL queryMin() {
		for (int i = 0; i <= 62; i++) if (d[i]) return d[i];
		return -1LL;
	}

	void rebuild() {
		for (int i = 62; ~i; i--) {
			for (int j = i - 1; ~j; j--) {
				if (d[i] & (1LL << j)) d[i] ^= d[j];
			}
		}
		for (int i = 0; i <= 62; i++) if (d[i])
				nd[tot++] = d[i];
	}

	LL kth(LL k) {
		if (flag) k--;
		if (!k) return 0LL;
		if (k >= (1LL << tot)) return -1LL;
		LL ans = 0;
		for (int i = 62; ~i; i--) {
			if (k & (1LL << i)) ans ^= nd[i];
		}
		return ans;
	}

	void merge(Base b) {//与b取并集
		for (int i = 62; ~i; i--) if (b.d[i])
				ins(b.d[i]);
	}

	Base mixed(Base B) {//与b取交集
		Base All, C, D;
		All.init(), C.init(), D.init();
		for (int i = 62; ~i; i--) {
			All.d[i] = d[i];
			D.d[i] = 1LL << i;
		}
		for (int i = 62; ~i; i--) {
			if (B.d[i]) {
				LL v = B.d[i], k = 0;
				bool can = true;
				for (int j = 62; ~j; j--) {
					if (v & (1LL << j)) {
						if (All.d[j]) {
							v ^= All.d[j];
							k ^= D.d[j];
						} else {
							can = false;
							All.d[j] = v;
							D.d[j] = k;
							break;
						}
					}
				}

				if (can) {
					LL v = 0;
					for (int j = 62; ~j; j--) {
						if (k & (1LL << j)) {
							v ^= d[j];
						}
					}
					C.ins(v);
				}
			}
		}
		return C;
	}

} lb;

int n, w, q, x, y;

int main() {
	scanf("%d", &n);
	lb.init();
	for (int i = 1; i <= n; i++) {
		scanf("%d", &w);
		lb.ins(w);
	}
	scanf("%d", &q);
	while (q--) {
		scanf("%d %d", &x, &y);
		if (lb.canIns(x ^ y)) puts("NO");
		else puts("YES");
	}
	return 0;
}
原文地址:https://www.cnblogs.com/ChaseNo1/p/11750092.html