• BZOJ3811玛里苟斯


    Description

    从一个序列里面选择一些数异或起来,求所有异或方案的答案的 (k) 次方的期望值

    (n le 100000,1le k le 5)

    Solution

    对于 (k=1) 的情况,对于每一位分开考虑

    如果至少有一个数的当前位是 (1) 的,那么有一半的可能性为 (0)

    也就是如果一个异或方案为 (0) 那么选择其补就能能得到为 (1) 的结果

    使用期望的线性性即可

    对于 (k>1) 的部分,平方的时候二进制位的贡献并不独立,所以需要分开考虑

    发现题目中说的 (ans le 2^{63}),那么对于 (k ge 3) 的,对原序列建立线性基,其大小不会超过 (63/3=21)

    原序列能异或出来的数,每个会重复 (2^{n-siz}) 次,所以期望就是 (frac {sum}{2^k})

    所以这个部分 (dfs) 或者直接状压即可

    剩余的 (k=2) 的部分考虑平方的本质是两个位相乘进行贡献,考虑两个带 (1) 的位置是不是能进行贡献

    如果是一个数中两个位置不同,注意这里要再除掉 (2) 因为这里的异或方案不足

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    namespace yspm{
    	#define ul unsigned long long
    	inline ul read()
    	{
    		ul res=0; char k;
    		while(!isdigit(k=getchar()));
    		while(isdigit(k)) res=res*10+k-'0',k=getchar();
    		return res;
    	}
    	int p[30],s,siz,n,m,pos,las,cnt;
    	ul ans,a[100010];
    	inline void insert(int x)
    	{
    		for(int i=siz;i>=0;--i)
    		{
    			if(!(x>>i)) continue;
    			if(!p[i]){p[i]=x; pos++; break;}
    			else x^=p[i]; 
    		} return ;
    	}
    	inline void solve()
    	{
    		ul res=0;
    		for(int i=1;i<=n;++i) a[i]=read();
        	for(int i=0;i<=32;i++)
        	{
        		for(int j=0;j<=32;j++)
        		{
    		 		int fg1=0,fg2=0,fg3=0;
    		 		for(int k=1;k<=n;k++)
    		 		{
    		  		   	if(a[k]>>i&1)fg1=1;
    		 		   	if(a[k]>>j&1)fg2=1;
    		    	    if((a[k]>>i&1)!=(a[k]>>j&1))fg3=1;
    		     	   	if(fg1&&fg2&&fg3)break;
    		    	}
    		    	if(!fg1||!fg2)continue;
    		    	if(i+j-fg3-1<0)res++;
    		    	else ans+=1ull<<(i+j-fg3-1);
        		}
        	}
        	ans+=res>>1; res&=1; 
       		printf("%llu",ans);
        	if(res)printf(".5
    ");
        	else puts("");
        	return ;
    	}
    	signed main()
    	{
    		n=read(); m=read();
    		if(m==1)
    		{
    			ul res=0;
    			for(int i=1;i<=n;++i) res|=read();
    			if(res%2==0) printf("%llu
    ",res/2);
    			else printf("%llu.5
    ",res/2);
    			return 0; 	
    		}
    		if(m==2) solve();
    		if(m>=3)
    		{
    			for(int i=1;i<=n;++i) a[i]=read();
    			if(m==3) siz=22; else if(m==4) siz=15; else siz=12;
    			for(int i=1;i<=n;++i) insert(a[i]);
    			for(int i=0;i<=siz;++i) if(p[i]) a[cnt++]=p[i]; s=1<<pos;
    			for(int i=0;i<s;++i)
    			{
    				int x=0;
    				for(int j=0;j<cnt;++j) 
    				{
    					if((i>>j)&1) x^=a[j]; 
    				} 
    				int r1=0,r2=1;
    				for(int j=1;j<=m;++j)
    				{
    					r2*=x; r1*=x; r1+=r2>>pos; r2&=s-1;
    				}
    				ans+=r1; las+=r2; ans+=las>>pos; las&=s-1; 
    			} 
    			printf("%lld",ans); if(las) puts(".5"); else puts("");
    		}
    		return 0;
    	}
    }
    signed main(){return yspm::main();}
    
    ``
  • 相关阅读:
    CSS 内外边距
    CSS 边框
    android chrome this account already exists on your device
    linux s s r client ubuntu kali
    rEFInd 美化 windows
    sogou opensuse
    Ping 虚拟机 超时
    python3 批量自动下载对应用户 github上的项目 或者 starts 的项目
    materialize 样例
    opensuse input methods
  • 原文地址:https://www.cnblogs.com/yspm/p/13394913.html
Copyright © 2020-2023  润新知