zoukankan      html  css  js  c++  java
  • 小米网络赛 热身赛 J题 XOR

    https://ac.nowcoder.com/acm/contest/8409/J

    Pro:
    给定(n)个数字
    求所有异或和为(0)的子集的子集大小之和
    (n<=1e5)

    Sol:
    考虑一个弱化版本
    求所有异或和为(0)的子集个数
    考虑求一个线性基
    设其大小为m
    答案即为((2^{n-m}-1))
    证明的话考虑
    把答案分成两部分
    包含非基底元素的和不包含非基底元素的

    1.包含非基底元素
    性基中的元素可以随便选
    因为它们组合出的任意元素都一定可以被基底中的一组解唯一表示,从而异或和为0
    因此贡献为((2^{n-m}-1))

    2.不包含非基底元素
    有线性基的性质可知其=0一定只有平凡解
    故这部分的贡献为0

    在这个做法的基础上稍作改动就可以得到
    求所有异或和为(k)的子集个数的做法
    这里不做赘述

    再来考虑本题
    根据刚才的讨论
    我们很容易得到一个(n*64*64)的做法
    即对于每个元素分别算贡献
    也就是去计算其它n-1个元素的异或和为k的子集个数
    这个只需要维护一个前缀线性基和后缀线性基即可
    但显然这个题还需要一个更为优秀的做法

    仔细观察可以发现
    我们对这n个元素求一遍线性基后
    非基底元素的贡献是非常好计算的
    设线性基大小为m
    对于任意非基底元素,它的贡献显然是(2^{n-m-1})
    因为非基底元素中任意一个组合都可以被基底元素表示
    这样的话只需要再对非基底元素使用原方法进行计算
    总复杂度O(64^3+n*logn)

    #include<bits/stdc++.h>
    #define M 63
    #define N 110000
    #define db double
    #define ll long long
    #define ldb long double
    #define ull unsigned long long
    using namespace std;
    const ll h=3,ki=149,mo=1e9+7;
    ll mod(ll x){return (x%mo+mo)%mo;}
    ll inc(ll x,ll k){x+=k;return x<mo?x:x-mo;}
    ll dec(ll x,ll k){x-=k;return x>=0?x:x+mo;}
    ll ksm(ll x,ll k)
    {
    	ll ans=1;
    	while(k){if(k&1)ans=1ll*ans*x%mo;k>>=1;x=1ll*x*x%mo;}
    	return ans;
    }
    ll inv(ll x){return ksm(mod(x),mo-2);}
    ll read()
    {
    	char ch=0;ll x=0,flag=1;
    	while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}
    	while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0',ch=getchar();}
    	return x*flag;
    }
    void write(ll x)
    {
    	if(!x)return (void)putchar(48);
    	if(x<0)putchar(45),x=-x;
    	ll len=0,p[20];
    	while(x)p[++len]=x%10,x/=10;
    	for(ll i=len;i>=1;i--)putchar(p[i]+48);
    }
    const db eps=1e-7,inf=1e9+7,pi=acos(-1);
    db Read(){db x;scanf("%lf",&x);return x;}
    void Write(db x){printf("%lf",x);}
    struct node
    {
    	ll size,f[M];
    	void clear(){size=0;for(ll i=62;i>=0;i--)f[i]=0;}
    	bool query(ll x)
    	{
    		for(ll i=62;i>=0;i--)if(1ll<<i&x){if(f[i])x^=f[i];else return false;}
    		return true;
    	}
    	bool insert(ll x)
    	{
    		for(ll i=62;i>=0;i--)if(1ll<<i&x){if(f[i])x^=f[i];else{size++,f[i]=x;return true;}}
    		return false;
    	}
    };
    node merge(const node &a,const node &b)
    {
    	node ans=a;
    	for(ll i=62;i>=0;i--)if(b.f[i])ans.insert(b.f[i]);
    	return ans;
    }
    node S,P;
    ll a[N],p[N];
    int main()	
    {
    	ll n;
    	while(~scanf("%lld",&n))
    	{
    		ll ans=0,cnt=0;
    		S.clear();P.clear();
    		for(ll i=1;i<=n;i++)
    		{
    			a[i]=read();
    			if(S.insert(a[i]))p[++cnt]=i;else P.insert(a[i]);
    		}
    		if(S.size<n)ans=1ll*(n-S.size)*ksm(2,n-S.size-1)%mo;
    		for(ll i=1;i<=cnt;i++)
    		{
    			node t=P;
    			for(ll j=1;j<=cnt;j++)if(i!=j)t.insert(a[p[j]]);
    			if(t.query(a[p[i]]))ans=inc(ans,ksm(2,n-1-t.size));
    		}
    		write(ans);putchar('
    ');
    	}
    	return 0; 
    }
    
  • 相关阅读:
    JavaSE—集合框架
    JavaSE——集合框架
    RocketMq 在Netty 下是如何进行消息封装传输
    SpringBoot 初始化流程以及各种常见第三方配置的源码实现
    Java 重要知识点,踩过的坑
    Mysql 知识储备以及InnoDB
    java 编程英语单词,语句
    PlantUML
    Rocketmq broker 消息仓库
    AutowiredAnnotationBeanPostProcessor 的一些思考
  • 原文地址:https://www.cnblogs.com/Creed-qwq/p/13961885.html
Copyright © 2011-2022 走看看