zoukankan      html  css  js  c++  java
  • UOJ#36. 【清华集训2014】玛里苟斯 线性基

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ36.html

    题解

    按照 $k$ 分类讨论:

    k=1 : 我们考虑每一位的贡献。若有至少一个数第 $i$ 位为 $1$ ,则对答案的贡献为 $2^i/2$ 。

    k=2 : 发现每个异或和的平方为 $sum_isum_j2^{i+j}bit_ibit_j$。那么考虑第 $i$ 位和第 $j$ 位的积的期望值。如果所有的数中,第 $i$ 位和第 $j$ 位均相等且非全零,那么参考 k=1 的情况,期望为 1/2;否则,第 $i$ 位为 $1$ 的概率为 1/2,第 $j$ 位为 $1$ 的概率为 1/2,$i×j$ 为 $1$ 的概率为 0.25 。
    $kleq 3$ : 由于答案不超过 $2^{63}$ ,直接把线性基搞出来之后暴力枚举就好了。

    代码

    #include <bits/stdc++.h>
    #define clr(x) memset(x,0,sizeof (x))
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    LL read(){
    	LL x=0,f=0;
    	char ch=getchar();
    	while (!isdigit(ch))
    		f|=ch=='-',ch=getchar();
    	while (isdigit(ch))
    		x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    	return f?-x:x;
    }
    const int N=100005;
    int n,k;
    ULL a[N];
    void init(){
    	static ULL x[64];
    	clr(x);
    	n=read(),k=read();
    	for (int i=1;i<=n;i++){
    		ULL v=read();
    		for (int i=63;~i;i--)
    			if (v>>i&1ULL)
    				if (!x[i]){
    					x[i]=v;
    					break;
    				}
    				else
    					v^=x[i];
    	}
    	n=0;
    	for (int i=63;~i;i--)
    		if (x[i])
    			a[++n]=x[i];
    }
    void Out(ULL x){
    	cout<<x/2;
    	if (x&1LLU)
    		cout<<".5";
    }
    namespace k1{
    	void solve(){
    		ULL ans=0;
    		for (int i=1;i<=n;i++)
    			ans|=a[i];
    		Out(ans);
    	}
    }
    namespace k2{
    	void solve(){
    		ULL ans=0;
    		for (int i=0;i<33;i++)
    			for (int j=0;j<33;j++){
    				int f1=0,f2=0,f=0;
    				for (int t=1;t<=n;t++){
    					f1|=a[t]>>i&1ULL;
    					f2|=a[t]>>j&1ULL;
    					f|=(a[t]>>i&1ULL)!=(a[t]>>j&1ULL);
    				}
    				if (!f1||!f2)
    					continue;
    				ans+=1ULL<<(i+j-f);
    			}
    		Out(ans);
    	}
    }
    namespace k3{
    	__int128 tot;
    	__int128 Pow(__int128 x,int y){
    		__int128 ans=1;
    		for (;y;y>>=1,x*=x)
    			if (y&1)
    				ans*=x;
    		return ans;
    	}
    	void solve(){
    		tot=0;
    		for (int i=(1<<n)-1;i>=0;i--){
    			ULL tmp=0;
    			for (int j=0;j<n;j++)
    				if (i>>j&1)
    					tmp^=a[j+1];
    			tot+=Pow(tmp,k);
    		}
    		while (tot%2==0&&n>1)
    			n--,tot/=2;
    		cout<<(ULL)tot/2;
    		if (tot%2==1)
    			cout<<".5";
    	}
    }
    int main(){
    	init();
    	if (k==1)
    		k1::solve();
    	else if (k==2)
    		k2::solve();
    	else
    		k3::solve();
    	return 0;
    }
    

      

  • 相关阅读:
    MiniUI表单验证实践
    MiniUI官方表单验证示例
    MiniUI表单验证总结
    Js-事件分发与DOM事件流
    Windows远程桌面连接的利器-mRemote
    Git 以分支的方式同时管理多个项目
    GIT 如何合并另一个远程Git仓库的文件到本地仓库里某个指定子文件夹并不丢失远程提交记录?
    如何导入另一个 Git库到现有的Git库并保留提交记录
    Total Commander如何设置自定义快捷键在当前目录打开ConEmu
    PHP ECSHOP中 诡异的问题:expects parameter 1 to be double
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/UOJ36.html
Copyright © 2011-2022 走看看