zoukankan      html  css  js  c++  java
  • 2019牛客多校一 H. XOR (线性基)

    大意: 给定序列, 求所有异或和为$0$的子序列大小之和.

    先求出线性基, 假设大小为$r$.

    对于一个数$x$, 假设它不在线性基内, 那么贡献为$2^{n-r-1}$

    因为它与其余不在线性基内数的任意组合后均可以与线性基异或后变为$0$, 产生$1$的贡献.

    所以问题就转化为求多少个数可以不在线性基内.

    现任意求出一组线性基, 然后再暴力验证该组线性基内的数即可.

    #include <iostream>
    #include <sstream>
    #include <algorithm>
    #include <cstdio>
    #include <math.h>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    #include <string.h>
    #include <bitset>
    #define REP(i,a,n) for(int i=a;i<=n;++i)
    #define PER(i,a,n) for(int i=n;i>=a;--i)
    #define hr putchar(10)
    #define pb push_back
    #define lc (o<<1)
    #define rc (lc|1)
    #define mid ((l+r)>>1)
    #define ls lc,l,mid
    #define rs rc,mid+1,r
    #define x first
    #define y second
    #define io std::ios::sync_with_stdio(false)
    #define endl '
    '
    #define DB(a) ({REP(__i,1,n) cout<<a[__i]<<' ';hr;})
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pii;
    const int P = 1e9+7, INF = 0x3f3f3f3f;
    ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
    ll qpow(ll a,ll n) {ll r=1%P;for (a%=P;n;a=a*a%P,n>>=1)if(n&1)r=r*a%P;return r;}
    ll inv(ll x){return x<=1?1:inv(P%x)*(P-P/x)%P;}
    inline int rd() {int x=0;char p=getchar();while(p<'0'||p>'9')p=getchar();while(p>='0'&&p<='9')x=x*10+p-'0',p=getchar();return x;}
    //head
    
    
    
    const int N = 1e5+10;
    int n, vis[N];
    ll a[N];
    struct _ {
        ll a[66];
    	_ () {memset(a,0,sizeof a);}
        inline bool ins(ll x) {
            REP(i,1,*a) x=min(x,a[i]^x);
            return x?a[++*a]=x:0;
        }
        inline _ operator + (const _ &rhs) const {
            _ r;
            REP(i,0,*a) r.a[i]=a[i];
            REP(i,1,rhs.a[0]) r.ins(rhs.a[i]);
            return r;
        }
    	inline int chk(ll x) {
    		REP(i,1,*a) x=min(x,a[i]^x);
    		return !x;
    	}
    } pre[N], suf[N];
    
    int main() {
    	while (~scanf("%d", &n)) {
    		REP(i,1,n) {
    			scanf("%lld", a+i);
    			if ((pre[i]=pre[i-1]).ins(a[i])) vis[i] = 1;
    		}
    		if (pre[n].a[0]==n) {
    			puts("0");
    			continue;
    		}
    		suf[n+1] = _();
    		PER(i,1,n) (suf[i]=suf[i+1]).ins(a[i]);
    		int sum = 0;
    		REP(i,1,n) { 
    			if (!vis[i]) ++sum;
    			else { 
    				vis[i] = 0;
    				if ((pre[i-1]+suf[i+1]).chk(a[i])) ++sum;
    			}
    		}
    		int ans = sum*qpow(2,n-pre[n].a[0]-1)%P;
    		printf("%d
    ", ans);
    	}
    }
    
  • 相关阅读:
    dubbo入门(一)
    java中文件操作《一》
    Unity 游戏框架搭建 2019 (七) 自定义快捷键
    凉鞋:我所理解的框架 【Unity 游戏框架搭建】
    Unity 游戏框架搭建 2019 (六) MenuItem 复用
    Unity 游戏框架搭建 2019 (五) 打开所在文件夹
    Unity 游戏框架搭建 2019 (四) 导出 UnityPackage
    Unity 游戏框架搭建 2019 (三) 生成文件名到剪切板
    Unity 游戏框架搭建 2019 (二) 文本复制到剪切板
    Unity 游戏框架搭建 2019 (一) 简介与第一个示例文件名的生成
  • 原文地址:https://www.cnblogs.com/uid001/p/11215904.html
Copyright © 2011-2022 走看看