• 【BZOJ3811】玛里苟斯(线性基)


    【BZOJ3811】玛里苟斯(线性基)

    题面

    BZOJ

    题解

    (K=1)很容易吧,拆位考虑贡献,所有存在的位出现的概率都是(0.5),所以答案就是所有数或起来的结果除二。
    (K=2)的情况,我们直接拆开平方式,平方项的贡献直接算,出现的概率还是(0.5),然后(2ab)这样子的东西出现的概率是(0.5*0.5=0.25),然而注意到有一些位直接两两之间存在联系,即选择了第(i)位的时候必定会同时选择第(j)位,那么此时两位之间的概率就是(0.5),这一部分要特殊判断一下。
    接下来考虑(Kge 3)的情况。因为答案不会超过(2^{63}),所以任何一个数字都不会从超过(2^{22})。我们知道如果一个数可以被线性基中的其他所有数给表示出来,那么这个数出现的概率一定是(1/{2^{|G|}}),其中(|G|)是线性基内的元素个数。既然数字大小不大,那么线性基中的元素个数也不多,所以可以构建线性基之后直接(2^{|G|})枚举所有可能出现的数字,(K)次方之后求和即可。
    注意一下,最终答案除掉总的数字个数之后在(2^{63})以内,那么在除之前是可能爆掉的,所以这里可以拆位什么的存一下就好了。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    inline ull read()
    {
    	ull x=0;bool t=false;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=true,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return t?-x:x;
    }
    int n,K;ull a[100100];
    namespace Task1
    {
    	void Solve()
    	{
    		ull ans=0;
    		for(int i=1;i<=n;++i)ans|=a[i];
    		if(ans&1)printf("%llu.5
    ",ans>>1);
    		else printf("%llu
    ",ans>>1);
    	}
    }
    namespace Task2
    {
    	bool vis[50];
    	bool check(int x,int y)
    	{
    		if(!vis[x]||!vis[y])return false;
    		for(int i=1;i<=n;++i)
    		{
    			if((a[i]&(1ll<<x))&&!(a[i]&(1ll<<y)))return false;
    			if((a[i]&(1ll<<y))&&!(a[i]&(1ll<<x)))return false;
    		}
    		return true;
    	}
    	void Solve()
    	{
    		ull ans=0;
    		for(int i=0;i<33;++i)
    			for(int j=1;j<=n;++j)
    				if(a[j]&(1ll<<i)){vis[i]=true;break;}
    		for(int i=0;i<33;++i)if(vis[i])ans+=1ll<<(i+i);
    		for(int i=0;i<33;++i)
    			for(int j=i+1;j<33;++j)
    				if(vis[i]&&vis[j])ans+=1ll<<(i+j);
    		for(int i=0;i<33;++i)
    			for(int j=i+1;j<33;++j)
    				if(check(i,j))ans+=1ll<<(i+j);
    		if(ans&1)printf("%llu.5
    ",ans>>1);
    		else printf("%llu
    ",ans>>1);
    	}
    }
    namespace Task3
    {
    	int p[50];
    	void insert(int x)
    	{
    		for(int i=30;~i;--i)
    			if(x&(1<<i))
    			{
    				if(!p[i]){p[i]=x;return;}
    				x^=p[i];
    			}
    	}
    	int S[55],top;
    	ull ans=0,r=0;
    	void Calc(int val)
    	{
    		int MOD=1<<top;
    		ull D=0,R=1;
    		for(int i=1;i<=K;++i)
    		{
    			D*=val;R*=val;
    			D+=R/MOD;R%=MOD;
    		}
    		ans+=D;r+=R;
    		ans+=r/MOD;r%=MOD;
    	}
    	void dfs(int x,int val)
    	{
    		if(x==top+1){Calc(val);return;}
    		dfs(x+1,val);dfs(x+1,val^S[x]);
    	}
    	void Solve()
    	{
    		for(int i=1;i<=n;++i)insert(a[i]);
    		for(int i=0;i<=30;++i)if(p[i])S[++top]=p[i];
    		dfs(1,0);
    		if(r)printf("%llu.5
    ",ans);
    		else printf("%llu
    ",ans);
    		return;
    	}
    }
    int main()
    {
    	n=read(),K=read();
    	for(int i=1;i<=n;++i)a[i]=read();
    	if(K==1){Task1::Solve();return 0;}
    	if(K==2){Task2::Solve();return 0;}
    	if(K>=3){Task3::Solve();return 0;}
    	return 0;
    }
    
  • 相关阅读:
    Jvm性能监控和常用工具
    JVM内存分配和回收策略
    从ExtensionLoader理解Dubbo扩展机制
    类的加载和双亲委派模型
    截器和过滤器的区别
    Struts2的工作原理
    Action
    StrutsPrepareAndExecuteFilter
    单例模式
    Web工作原理
  • 原文地址:https://www.cnblogs.com/cjyyb/p/10056615.html
Copyright © 2020-2023  润新知