链接:https://www.nowcoder.com/acm/contest/180/D
来源:牛客网
题目描述
小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<=105 保证所有运算均在int范围内
性质:若$x \oplus z=y$, 则$x \oplus y=z$
考虑答案一定是$x \oplus {$一坨东西$}=y$
那么$x \oplus y = {$一坨东西$}$
因此问题变为询问序列中是否有$x \oplus y$
->线性基经典操作
时间复杂度:$O(nlogn)$
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 32, B = 31;
inline int read() {
char c = getchar(); int x = 0, f = 1;
while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int N;
int P[MAXN];
void Insert(int x) {
for(int i = B; i >= 0; i--) {
if((x >> i) & 1) {
if(!P[i]) {P[i] = x; break;}
x ^= P[i];
}
}
}
int Query(int x) {
for(int i = B; i >= 0; i--) {
if((x >> i) & 1) {
if(!P[i]) return 0;
x ^= P[i];
}
}
if(x == 0) return 1;
else return 0;
}
int main() {
N = read();
for(int i = 1; i <= N; i++) {
int val = read(); Insert(val);
}
int Q = read();
while(Q--) {
int x = read(), y = read();
if(Query(x ^ y)) puts("YES");
else puts("NO");
}
}