zoukankan      html  css  js  c++  java
  • 2019牛客暑期多校训练营(第一场):XOR(线性基)

    题意:给定数组,求所有异或起来为0的集和的大小之和。

    思路:由于是集合大小,我们换成考虑每个元素在多少个集合里有贡献。 先生成线性基。

    对于没有插入线性基的元素x,贡献是2^(N-base-1),因为x选择之后,其他非基元素无论选还是不选,都可以调整基来使得异或和为0。

    对于插入线性基的元素x,我们也同样这样考虑,把除了它的N-1个数生成线性基。 就可以同样算贡献了。 这里现在可以稍加优化,把最开始的非基元素预处理成一个线性基,这样生成新的线性基就快起来了。

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    #define rep2(i,a,b) for(int i=a;i>=b;i--)
    using namespace std;
    const int maxn=2000010;
    const int Mod=1e9+7;
    ll a[maxn],b[maxn],c[maxn],used[maxn]; int tot;
    int qpow(int a,int x){
        int res=1; while(x){
            if(x&1) res=1LL*res*a%Mod;
            x>>=1; a=1LL*a*a%Mod;
        } return res;
    }
    bool add(ll x,ll base[])
    {
        rep2(i,63,0) {
            if(x&(1LL<<i)){
                if(!base[i]){ base[i]=x; return true;}
                x^=base[i];
            }
        }
        return false;
    }
    int main()
    {
        int N,ans=0;  ll x;
        while(~scanf("%d",&N)){
           rep(i,0,63) a[i]=b[i]=c[i]=0; tot=0;
           rep(i,1,N) {
              scanf("%lld",&x);
              if(add(x,a)) used[++tot]=x;
              else add(x,b);
           }
           if(tot<N) ans=1LL*qpow(2,N-tot-1)*(N-tot)%Mod;
           rep(i,1,tot){
               rep(j,0,63) c[j]=b[j];
               rep(j,1,tot) if(i!=j) add(used[j],c);
               if(!add(used[i],c)) (ans+=qpow(2,N-tot-1))%=Mod;
           }
           printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    sqlserver 字符串拆分和取某分隔符之前的字符串
    三目运算符引发的一次事故
    SqlServer 查询死锁,杀死死锁进程*转载
    sql不带锁查询
    各种replace待续
    jmeter压力测试
    docker基础学习
    被动式pocscan扫描神器搭建
    (转)Ubuntu 17.04_64上搭建巡风扫描系统(资产信息漏洞扫描内网神器)
    (转)搭建本地 8.8 W 乌云漏洞库
  • 原文地址:https://www.cnblogs.com/hua-dong/p/11463064.html
Copyright © 2011-2022 走看看