【線性基】NC180D-xor序列
阿新 • • 發佈:2021-11-19
題目描述
小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; }