1. 程式人生 > 其它 >【線性基】NC180D-xor序列

【線性基】NC180D-xor序列

題目連結

題目描述

小a有n個數,他提出了一個很有意思的問題:他想知道對於任意的x, y,能否將x與這n個數中的任意多個數異或任意多次後變為y

輸入描述:

第一行為一個整數n,表示元素個數
第二行一行包含n個整數,分別代表序列中的元素
第三行為一個整數Q,表示詢問次數
接下來Q行,每行兩個數x,y,含義如題所示

輸出描述:

輸出Q行,若x可以變換為y,輸出“YES”,否則輸出“NO”

示例1

輸入
5
1 2 3 4 5
3
6 7 
2 1
3 8
輸出
YES
YES
NO
說明
對於(6,7)來說,6可以先和3異或,再和2異或
對於(2,1)來說,2可以和3異或
對於(3,8)來說,3不論如何都不能變換為8
備註:
對於100%的資料,n,Q<=10^5
保證所有運算均在int範圍內

題意

如題,判斷一個數能否被當前線性基中的元素異或得到,q次查詢

思路

關於線性基

向量空間的基:向量空間中最大的線性無關組成為該向量空間的一組基

線性基:一般指模2空間(異或)下的一個子空間的基

應用範圍:求一個集合S中取一個子集異或得到所有數的數量;求一個集合S中取一個子集異或可以得到的最大/小值

關於異或的小性質:

如果a ^ b ^ c == 0,則a ^ b == c;

如果a ^ b == c,則a ^ c == b;

線性基的性質之一:原序列裡面的任意一個數都可以由線性基裡面的一些數異或得到

所以嘗試把得到的數插到線性基裡面去,如果可以插入說明不能異或得到,如果插不進去說明可以異或得到

(初學,記錄很板子的操作)

AC程式碼

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define inf 0x3f3f3f3f
#define PII pair<int,int>
#define endl '\n'
const int N = 5e5 + 10;
const int mod = 1e9 + 7;
const double pi = acos(-1.0);
typedef long long ll;
int t, n, m;
int base[65];//最高位為第i位的基
void insert(int x) {
	for (int i = 32; i >= 0; i--) {
		if (x & (1ll << i)) {//如果i大於31,1後面要加ll
			if (!base[i]) {
				base[i] = x;
				return;
			}
			x ^= base[i];
		}
	}
}
int find(int x) {
	for (int i = 32; i >= 0; i--) {
		if (x & (1ll << i)) {
			if (!base[i]) return 0;
			x ^= base[i];
		}
	}
	return 1;
}
void init() {
	for (int i = 0; i <= 64; i++) {
		base[i] = 0;
	}
	return;
}
void solve() {
	init();
	int x, y;
	for (int i = 1; i <= n; i++) {
		cin >> x;
		insert(x);
	}
	int q;
	cin >> q;
	while (q--) {
		cin >> x >> y;
		if (find(x ^ y)) cout << "YES" << endl;
		else cout << "NO" << endl;
	}
}
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	while (cin >> n) {
		solve();
	}
	return 0;
}