zoukankan      html  css  js  c++  java
  • Codeforces 959 F. Mahmoud and Ehab and yet another xor task

    (>Codeforcesspace959 F. Mahmoud and Ehab and yet another xor task<)

    题目大意 : 给出一个长度为 (n) 序列 (A),和 (q) 次询问,对于每一次询问给出两个数 (l, x) ,你需要计算在前缀和 (A[1, l]) 中选取若干个数,使得它们 (xor) 起来的结果等于 (x) 的方案数

    $n , q leq 10^5 0 leq A_i leq 2^{20} $

    解题思路 :

    首先考虑离线,发现将询问按照 (l) 排序之后,询问每一个 (l) 时都可以构造出关于前缀$ A[1,l] $的线性基

    考虑如果要在前缀 (A[1,l]) 中选取若干个数表示出 (x), 那么线性基中的元素必然能表示出 (x)

    与此同时,如果线性基能表示出 (x)

    那么对于每一个在前缀 (A[1, l]) 但不在线性基中元素 (A_i) 线性基都能表示出 ((x xor A_i))

    所以线性基外的元素都可以选或者不选,那么方案数就是 (2^{l -size}) 其中 (size) 指的是线性基的大小

    那么只需要对于询问离线,边向线性基内插入数边回答询问,判断是否能被线性基表示并算出线性基的大小即可

    判断数是否能被线性基表示 : 对于数每一个有 (1) 的二进制位,(xor) 上线性基的对应位,判断是否变成了 (0)

    求线性基的大小 : 加入元素的时候通过判断是否加入成功来维护


    /*program by mangoyang*/
    #include<bits/stdc++.h>
    #define inf (0x7f7f7f7f)
    #define Max(a, b) ((a) > (b) ? (a) : (b))
    #define Min(a, b) ((a) < (b) ? (a) : (b))
    #define P 1000000007
    typedef long long ll;
    using namespace std;
    template <class T>
    inline void read(T &x){
        int f = 0, ch = 0; x = 0;
        for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
        for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
        if(f) x = -x;
    }
    int a[200005], ans[200005], Bit[25], n, m, tot;
    struct Query{ int l, x, id; } q[200005];
    inline bool cmp(Query A, Query B){ return A.l < B.l; } 
    inline ll Pow(ll a, ll b){
        ll ans = 1;
        for(; b; b >>= 1, a = a * a % P)
            if(b & 1) ans = ans * a % P;
        return ans;
    }
    inline void ins(int x){
        for(int i = 19; ~i; i--) if((1 << i) & x){
            if(!Bit[i]){ Bit[i] = x; return; }
            x ^= Bit[i];
        }    
    }
    inline void Answer(Query now){
        int x = now.x, lim = now.l, id = now.id, cnt = 0;
        for(int i = 19; ~i; i--) if(Bit[i]){
            cnt++;
            if((1 << i) & x) x ^= Bit[i];
        }
        if(x) ans[id] = 0; else ans[id] = Pow(2, lim - cnt);
    }
    int main(){
        read(n), read(m);
        for(int i = 1; i <= n; i++) read(a[i]);
        for(int i = 1; i <= m; i++){
            int l, x;
            read(l), read(x), q[i] = (Query){l, x, i};
        }
        int p = 1;
        sort(q + 1, q + m + 1, cmp);
        for(; !q[p].l && p <= m; p++)
            if(!q[p].x) ans[q[p].id] = 1; else ans[q[p].id] = 0;
        for(int i = 1; i <= n; i++){
            ins(a[i]); 
            while(q[p].l == i && p <= m) Answer(q[p++]);
        }
        for(int i = 1; i <= m; i++) printf("%d
    ", ans[i]);
        return 0;
    }
    
  • 相关阅读:
    CleanWebpackPlugin
    webpack
    kubeadm部署k8s
    leetcode 148 链表排序的归并排序和插入排序
    102 二叉树层序遍历(一下出一层的广搜和DFS)
    139 单词拆分 dp
    48 旋转图像 水平翻转然后主对角线翻转即可实现顺时针旋转90°
    31下一个排列
    最长连续序列
    每日总结22——SQL语句(保持现有内容在后面增加内容)
  • 原文地址:https://www.cnblogs.com/mangoyang/p/9301364.html
Copyright © 2011-2022 走看看