zoukankan      html  css  js  c++  java
  • bzoj 2844 albus就是要第一个出场 异或和出现次数 线性基

    题目链接

    题意

    给定(n)个数,将其所有的子集((2^n)个)的异或和按升序排列。给出一个询问(q),问(q)在该序列中第一次出现位置的下标(下标从(1)开始)。

    题解

    结论

    记其线性基为(mathfrak B),则每个异或和出现的次数为(2^{n-|mathfrak B|}).

    证明

    高斯消元的角度看,将(n)个数看作(n)个行向量,经行等价变换后得到一个行简化梯形矩阵,非零行的行数为(|mathfrak B|),而下面的(n-|mathfrak B|)行为零行。

    从上面的(|mathfrak B|)行中取若干行,异或起来得到一个值(x);而在下面的(n-|mathfrak B|)行中无论取多少个与(x)进行异或,得到的值都仍为(x)(因为下面(n-|mathfrak B|)行的数均为(0)). 因为一共有(2^{n-|mathfrak B|})种取法,所以值(x)出现了(2^{n-|mathfrak B|})次。

    注意点

    无论这(n)个数是否线性相关,(0)都始终在序列中出现,因为子集可以为空集。

    进一步的,如果该(n)个数线性无关,则(0)只会出现一次,由线性无关的定义易知。
    对应于上面的结论,因线性无关,所以(|mathfrak B|=n,2^{n-|mathfrak B|}=1),也是吻合的。

    Code

    #include <bits/stdc++.h>
    #define mod 10086
    #define maxl 30
    using namespace std;
    typedef long long LL;
    LL poww(LL a, LL b) {
        LL ret = 1;
        while (b) {
            if (b & 1) (ret *= a) %= mod;
            (a *= a) %= mod;
            b >>= 1;
        }
        return ret;
    }
    struct LinearBasis {
        LL a[maxl+1]; int size; vector<int> v;
        LinearBasis() { memset(a, 0, sizeof(a)); size = 0; v.clear(); }
        void insert(LL t) {
            for (int i = maxl; i >= 0; --i) {
                if (!(t >> i & 1)) continue;
                if (a[i]) t ^= a[i];
                else {
                    ++size;
                    for (int j = 0; j < i; ++j) if (t >> j & 1) t ^= a[j];
                    for (int j = i+1; j <= maxl; ++j) if (a[j] >> i & 1) a[j] ^= t;
                    a[i] = t;
                    return;
                }
            }
        }
        void basis() {
            for (int i = 0; i <= maxl; ++i) if (a[i]) v.push_back(i);
        }
        LL rank(LL x) {
            LL ret = 0;
            for (int i = 0; i < v.size(); ++i) if (x >> v[i] & 1) ret += 1LL << i;
            return ret;
        }
    };
    int main() {
        int n, x, q;
        scanf("%d", &n);
        LinearBasis lb;
        for (int i = 0; i < n; ++i) scanf("%d", &x), lb.insert(x);
        lb.basis();
        scanf("%d", &q);
        LL num = poww(2, n - lb.size);
        printf("%lld
    ", (lb.rank(q) % mod * num % mod + 1) % mod);
        return 0;
    }
    
    
  • 相关阅读:
    题解 UVA120 【煎饼 Stacks of Flapjacks】
    信息编码表示

    二叉树
    逻辑运算&位运算
    POJ2425 Ubiquitous Religions(并查集板题)
    CF1426E Rock, Paper, Scissors 题解
    POJ2478 Farey Sequence
    dubbo+zookeeper报错 KeeperErrorCode = Unimplemented for /dubbo
    代码无法提交到GitHub: Remote URL test failed: git@github.com: Permission denied (publickey)
  • 原文地址:https://www.cnblogs.com/kkkkahlua/p/7808275.html
Copyright © 2011-2022 走看看