牛客练习赛26 D xor序列 (线性基)
链接:https://ac.nowcoder.com/acm/contest/180/D
来源:牛客网
xor序列
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
小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范围内
题意:
   
 思路:
异或的性质:
y^y=0 则 xyy=x
令 x^z=y 两边异或x , 则 xzx=y^x -> z= y^x
即在数组中 找出一些数异或起来等于z即可。
这恰好是线性基的基础功能。
细节见代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define rt return
#define dll(x) scanf("%I64d",&x)
#define xll(x) printf("%I64d\n",x)
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll powmod(ll a,ll b,ll MOD){ll ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
inline void getInt(int* p);
const int maxn=1000010;
const int inf=0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
struct LB {
    // 注意最高是60还是62
    ll d[61], p[61];
    int cnt, mx;
    LB() {
        memset(d, 0, sizeof(d));
        memset(p, 0, sizeof(p));
        cnt = 0, mx = 61;
    }
    void init() {
        memset(d, 0, sizeof(d));
        memset(p, 0, sizeof(p));
    }
    bool add(ll val) {
        /*插入时判断之前是否有数会与val异或得0,判第k小时如果有为0的情况,k要减一*/
        for (int i = mx - 1; i >= 0; i--) {
            if (val & (1LL << i)) {
                if (!d[i]) {
                    d[i] = val; break;
                }
                val ^= d[i];
            }
        }
        return val > 0;
    }
    bool query(ll val) { // 查询val这个数是否存在
        for (int i = mx - 1; i >= 0; i--) {
            if (val & (1LL << i)) {
                if (!d[i]) return 0;
                val ^= d[i];
            }
        }
        return 1;
    }
    ll query_max(ll val) {
        ll ret = val;
        for (int i = mx - 1; i >= 0; i--) if ((ret ^ d[i]) > ret) ret ^= d[i];
        return ret;
    }
    ll query_min() {
        for (int i = 0; i < mx; i++) if (d[i]) return d[i];
        return 0;
    }
    void rebuild() {//消元,保存到p数组
        cnt = 0;
        for (int i = 0; i < mx; i++) {
            for (int j = 0; j < i; j ++ )
                if (d[i] & (1LL << j)) d[i] ^= d[j];
        }
        for (int i = 0; i < mx; i++) if (d[i]) p[cnt++] = d[i];
    }
    ll query_kth(ll k) { //使用前需要rebuild
        ll ret = 0;
        if (k >= (1LL << cnt)) return -1;
        for (int i = cnt - 1; i >= 0; i--) if (k & (1LL << i)) ret ^= p[i];
        return ret;
    }
    ll find(ll x) { //找x是第几大的数,需保证x一定在
        ll ret = 0, c = 0;
        for (int i = 0; i < mx; i++) {
            if (d[i]) {
                if (x >> i & 1) ret += (1LL << c);
                c++;
            }
        }
        return ret;
    }
    LB operator+(const LB & _A)const {  //合并
        LB ret = *this;
        for (int i = mx - 1; i >= 0; i--) if (_A.d[i]) ret.add(_A.d[i]);
        return ret;
    }
};
LB base=LB();
int main()
{
    //freopen("D:\\common_text\\code_stream\\in.txt","r",stdin);
    //freopen("D:\\common_text\\code_stream\\out.txt","w",stdout);
    int q;
    int n,x;
    cin>>n;
    repd(i,1,n)
    {
        cin>>x;
        base.add(x);
    }
    cin>>q;
    int y;
    while(q--)
    {
        cin>>x>>y;
        x^=y;
        if(base.query(x))
        {
            cout<<"YES"<<endl;
        }else
        {
            cout<<"NO"<<endl;
        }
    }
    return 0;
}
inline void getInt(int* p) {
    char ch;
    do {
        ch = getchar();
    } while (ch == ' ' || ch == '\n');
    if (ch == '-') {
        *p = -(getchar() - '0');
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 - ch + '0';
        }
    }
    else {
        *p = ch - '0';
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 + ch - '0';
        }
    }
}
牛客练习赛26 D xor序列 (线性基)的更多相关文章
- 牛客练习赛26—D xor序列  —线性基
		这是我第一次写关于线性基的题目.其实这题很好理解,先把给出的数能异或出的值给存在p数组里面,p[i]代表着该异或出的数的最高位为第i位且为1. 求出来后,再把x,y处理下,然后直接一位一位的判断是否为 ... 
- Nowcoder 练习赛26 D xor序列 ( 线性基 )
		题目链接 题意 : 中文题.点链接 分析 : 对于给定的 X 和 Y 假设存在一个 Z 使得 X (xor) Z = Y 做一个变形 X (xor) Z (xor) Y = 0 X (xor) Y = ... 
- 牛客练习赛26:D-xor序列(线性基)
		链接:牛客练习赛26:D-xor序列(线性基) 题意:小a有n个数,他提出了一个很有意思的问题:他想知道对于任意的x, y,能否将x与这n个数中的任意多个数异或任意多次后变为y 题解:线性基 #inc ... 
- 牛客练习赛26 xor序列
		xor序列 思路:线性基 代码: #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include< ... 
- 牛客 - 17968 - xor序列 - 线性基
		https://ac.nowcoder.com/acm/problem/17968 下面是错误的做法,因为题目要求必须使用x,而y在check的时候不一定用到等价于x的线性基来构成. 正确的做法是直接 ... 
- 牛客练习赛26  E-树上路径 (树链剖分+线段树)
		链接:https://ac.nowcoder.com/acm/contest/180/E 来源:牛客网 树上路径 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 262144K,其他语 ... 
- 牛客练习赛 26 C题 城市规划【贪心】
		<题目链接> 题目描述 小a的国家里有n个城市,其中第i和第i - 1个城市之间有无向道路连接,特殊的,第1个城市仅与第2个城市相连为了减轻道路维护负担,城市规划局局长MXT给出了m个要求 ... 
- 牛客练习赛70  B.拼凑  (序列自动机)
		题意:有一个模板串,有\(T\)个字符串,从字符串中找到某个子串,使得这个子串中的子序列包含模板串,求最短的子串的长度. 题解:找子序列,很容易想到序列自动机,根据序列自动机的原理,我们一定可以确保除 ... 
- 牛客练习赛 26 B题 烟花【DP】(经典)
		<题目链接> 题目描述 小a有个烟花,每个烟花代表着互不相同的颜色,对于第个烟花,它有的概率点燃,现在小a要去点燃它们,他想知道产生颜色的期望个数 及 产生恰好产生种颜色的概率 输入描述: ... 
随机推荐
- D5(太长了md没写完)
			动态规划 三种常见实现方法 对于一个斐波那契数列,我们想要求第n项的值,就需要一项一项的递归来求 来看代码 f[o] = 0; f[1] = 1; for (int i = 2; i <= n; ... 
- Ubuntu:Unable to locate package ***
			在Ubuntu 上使用apt-get 安装包时遇到 Unable to locate package 的信息 解决方案: 更细apt-get然后重新安装 #sudo apt-get update ... 
- 【10】css设置文字不换行,超过的部分用“...”代替
			设置文字不换行,超过的部分用“...”代替 overflow: hidden; text-overflow: ellipsis; white-space: nowrap; width: 210 ... 
- 前端必须掌握的 nginx 技能(2)
			概述 作为一个前端,我觉得必须要学会使用 nginx 干下面几件事: 代理静态资源 设置反向代理(添加https) 设置缓存 设置 log 部署 smtp 服务 设置 redis 缓存(选) 下面我按 ... 
- 阶段3 2.Spring_07.银行转账案例_7 代理的分析
			新建项目 实现动态代理. 动态代理的概念 买电脑找代理商 代理的出现 解决了生产厂家的一些问题 需要java中的动态代理机制 
- java游戏服务器  策略+简单工厂
			上一篇中我们讲到简单工厂模式有它的弊端,它不好在哪里呢? 我们看到,每次创建场景,我们都需要暴露两个类... 这是比较不好的, 可以通过策略模式+简单工厂模式来稍微改造下 一.先来一个策略模式UML图 ... 
- java驼峰法和下划线法字符串的相互转换
			java驼峰法和下划线法字符串的相互转换 1 import java.util.regex.Matcher; import java.util.regex.Pattern; public class ... 
- oop理论
			三大特性: 封装:把对象的属性和行为独立的一个整体,并尽可能的隐藏对象内部实现细节.增加安全性. 继承:从已有的类中派生出新的类,称为子类,子类继承父类的属性和行为,并能根据自己的需求扩展出新的行为. ... 
- DMA(Direct Memory Access直接存储器访问)总结
			转载于http://blog.csdn.net/peasant_lee/article/details/5594753 DMA一种高速的数据传输操作,允许在外部设备和存储器之间直接读写数据,不需要CP ... 
- Python密码登录程序的思考--学与习
			# 初学者的起步,对于开始的流程图结构还不太熟悉 # 思考: 1,write()与writelines()的区别,前者确定为字符串,后者为序列(列表,字典.元组等),自动为你迭代输入# ... 
