• BZOJ 2844: albus就是要第一个出场 [高斯消元XOR 线性基]


    2844: albus就是要第一个出场


    题意:给定一个n个数的集合S和一个数x,求x在S的$2^n$个子集从小到大的异或和序列中最早出现的位置


    一开始看错题了...人家要求的是x第一次出现位置不是第x个是谁

    求出线性基后我们知道一共有$2^r$个不同的数,再知道每个数出现了几次就好啦

    每个数出现了$2^{n-r}$次....因为有$n-r$个线性相关(高斯消元后全0了)的方程异或不影响....

    然后就简单了,从高到低枚举二进制位,异或这一位后小于k就加上

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <bitset>
    using namespace std;
    typedef long long ll;
    const int N=1e5+5,INF=1e9,P=10086;
    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,x;
    int a[N],bin[70];
    void ini(){
        bin[0]=1;for(int i=1;i<=30;i++) bin[i]=bin[i-1]<<1;
    }    
    int now;
    void Gauss(){
        now=1;
        for(int i=30;i>=0;i--){
            int j=now;
            while(j<=n&&!(a[j]&bin[i])) j++;
            if(j==n+1) continue;
            if(j!=now) swap(a[j],a[now]);
            for(int k=1;k<=n;k++) 
                if(k!=now&&(a[k]&bin[i])) a[k]^=a[now];
            now++;
        }
        now--;
    }
    int main(){
        freopen("in","r",stdin);
        ini();
        n=read();
        for(int i=1;i<=n;i++) a[i]=read();
        Gauss();
        x=read();
        int val=0,sum=0;
        for(int i=1;i<=now;i++) if((val^a[i])<=x){
            val^=a[i];
            sum=(sum+(1<<(now-i))%P)%P;
        }
        for(int i=1;i<=n-now;i++) sum=(sum<<1)%P;
        printf("%d",(sum+1)%P);
    }
  • 相关阅读:
    C#库
    大话设计模式--简单工厂模式
    weka平台下手动造.arff的数据
    NIM博弈的必胜取法
    求一个全排列函数: 如p([1,2,3])输出:[123],[132],[213],[231],[312],[321]. 求一个组合函数 如p([1,2,3])输出:[1],[2],[3],[1,2],[2,3],[1,3],[1,2,3]
    哥德巴赫猜想
    C#格式化输出
    meta文件里指定资源
    chromatic aberration
    uber shader
  • 原文地址:https://www.cnblogs.com/candy99/p/6415397.html
Copyright © 2020-2023  润新知