• 2019牛客暑期多校训练营(第一场)H 线性基+计算贡献


    题意

    给n个整数,求满足子集异或和为0的子集大小之和。

    分析

    将问题转化为求每个元素的贡献次数之和。

    先对n个数求线性基,设线性基大小为r,即插入线性基的数字个数为r,可以分别计算线性基内数的贡献和线性基外的数的贡献

    • 线性基外:共n-r个数,枚举每个数x,它可以和将线性基外剩余的n-r-1个数同时存在一个集合内,显然共有(2^{n-r-1})个集合,所以x的贡献为(2^{n-r-1})
    • 线性基内:枚举每个数x,将剩余的n-1个数再求一次线性基,设为B,分两种情况:
      • x不能被B异或出。那么显然x不能在任意一个集合中出现,x的贡献为0。
      • x可以被B异或出。此时B的大小必定也为r,因为B已经能表示所有n个数了。那么在除去x和B的情况下,x可以和剩余的n-r-1个数同时存在一个集合内,x的贡献为(2^{n-r-1})

    Code

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define pb push_back
    #define ll long long
    using namespace std;
    const int inf=1e9;
    const int mod=1e9+7;
    const int maxn=1e5+10;
    int n;
    ll a[maxn];
    struct node{
    	ll p[65];
    	int cnt;
    	void clear(){
    		cnt=0;
    		memset(p,0,sizeof(p));
    	}
    	bool insert(ll x){
    		for(int i=60;i>=0;i--){
    			if(x&(1ll<<i)){
    				if(!p[i]){
    					p[i]=x;cnt++;
    					return 1;
    				}
    				x^=p[i];
    			}
    		}
    		return 0;
    	}
    };
    node x,y,z;
    ll ksm(ll a,ll b){
    	ll ret=1;
    	while(b){
    		if(b&1) ret=ret*a%mod;
    		b>>=1;
    		a=a*a%mod;
    	}
    	return ret;
    }
    int main(){
    	//ios::sync_with_stdio(false);
    	//freopen("in","r",stdin);
    	while(~scanf("%d",&n)){
    		x.clear();y.clear();z.clear();
    		for(int i=1;i<=n;i++){
    			scanf("%lld",&a[i]);
    		}
    		vector<ll>q,res;
    		for(int i=1;i<=n;i++){
    			if(x.insert(a[i])){
    				q.pb(a[i]);
    			}else res.pb(a[i]);
    		}
    		if(n==x.cnt){
    			puts("0");
    			continue;
    		}
    		ll ans=1ll*(n-x.cnt)*ksm(2,n-x.cnt-1)%mod;
    		for(ll val:res){
    			y.insert(val);
    		}
    		for(ll i:q){
    			z=y;
    			for(ll j:q){
    				if(i==j) continue;
    				z.insert(j);
    			}
    			if(!z.insert(i)) ans=(ans+ksm(2,n-x.cnt-1))%mod;
    		}
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    sicp-py
    Ubuntu下找不到ttyUSB*问题解决
    Mysql基本命令及数据库存储位置
    open-vm-tools与VMware Tools
    64位ubuntu安装交叉编译工具链,显示找不到命令
    VMware Tools 继续运行脚本未能在虚拟机中成功运行。
    VMware Workstation 14安装VMware Tools
    VMware Workstation14 安装Ubuntu18.04
    Linux安装Sqlite
    mysql中文乱码
  • 原文地址:https://www.cnblogs.com/xyq0220/p/11366669.html
Copyright © 2020-2023  润新知