• 牛客练习赛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;
    }
    
  • 相关阅读:
    LINUX按键驱动程序
    s3c2440地址分配
    Linux内核代码
    C语言初始化
    tftp协议
    ARM工作模式
    Bootstrap3隐藏滑动侧边栏菜单代码特效
    javascript 中slice,substr,substring方法的对比
    vue 的简述
    鼠标移动出自己想要的效果
  • 原文地址:https://www.cnblogs.com/ChaseNo1/p/11750092.html
Copyright © 2020-2023  润新知