zoukankan      html  css  js  c++  java
  • bzoj 3811: 玛里苟斯【线性基+期望dp】

    这个输出可是有点恶心啊……WA*inf,最后抄了别人的输出方法orz
    还有注意会爆long long,要开unsigned long long
    对于k1,单独考虑每一位i,如果这一位为1则有0.5的概率贡献1<<i,否则没有贡献,因为这一位选了奇数偶数个1的概率是一样的
    对于k
    2,考虑乘法的意义,也就是i位和j位同时为1的概率p,贡献(1<<(i+j))*p,这个p,如果全部的a[k]都是在i位和j为相同则是p=0.5(因为这样一来ij的值就关联了),否则p=0.25
    对于剩下的,建线性基后最多有21个元素,直接枚举所有状态即可

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    const int N=100005;
    unsigned long long n,m,k,a[N],b[65],tot,ans,res;
    unsigned long long read()
    {
    	unsigned long long r=0,f=1;
    	char p=getchar();
    	while(p>'9'||p<'0')
    	{
    		if(p=='-')
    			f=-1;
    		p=getchar();
    	}
    	while(p>='0'&&p<='9')
    	{
    		r=r*10+p-48;
    		p=getchar();
    	}
    	return r*f;
    }
    void ins(unsigned long long x)
    {
    	for(int i=63;i>=0;i--)
    		if(x>>i)
    		{
    			if(!b[i])
    			{
    				b[i]=x;
    				return;
    			}
    			x^=b[i];
    		}
    }
    int main()
    {
    	n=read(),k=read();
    	for(int i=1;i<=n;i++)
    		a[i]=read();
    	if(k==1)
    	{
    		for(int i=1;i<=n;i++)
    			ans|=a[i];
    		printf("%llu",ans>>1),puts((ans&1)?".5":"");
    		return 0;
    	}
    	if(k==2)
    	{
    		unsigned s=0;
    		for(int i=1;i<=n;i++) 
    			s|=a[i];
    		for(int i=0;i<32;i++)
    			for(int j=0,fl=0;j<32;++j,fl=0)
    				if((s>>i&1)&&(s>>j&1))
    				{
    					for(int k=1;k<=n;k++)
    						if((a[k]>>i&1)^(a[k]>>j&1))
    						{
    							fl=1;
    							break;
    						}
    					if(i+j-1-fl<0) 
    						++res;
    					else ans+=1llu<<(i+j-1-fl);
    				}
    		ans+=res>>1;
    		printf("%llu",ans),puts((res&1)?".5":"");
    		return 0;
    	}
    	unsigned long long ans=0;
    	for(int i=1;i<=n;i++)
    		ins(a[i]);
    	// for(int i=0;i<=20;i++)
    		// cerr<<b[i]<<" ";cerr<<endl;
    	for(m=22;!b[m];m--);
    	m++;
    	for(int s=0,len=(1<<m);s<len;s++)
    	{
    		unsigned long long sm=0,r=1;
    		for(int i=0;i<m;i++)
    			if(s&(1<<i))
    				sm^=b[i];
    		for(int i=1;i<k;i++) 
    			r*=sm;
    		if(r<len)
    		{
    			r*=sm,tot+=r;
    			if(tot>=len) 
    				ans+=tot/len,tot%=len;
    		}
    		else
    		{
    			ans+=r/len*sm,r%=len,r*=sm,tot+=r;
    			if(tot>=len) 
    				ans+=tot/len,tot%=len;
    		}
    	}
    	printf("%llu",ans),puts(tot?".5":"");
    	return 0;
    }
    
  • 相关阅读:
    C# 模式&模式匹配
    CentOS7下安装 dotnet sdk
    PLSQL 设置
    Visual Studio Code 开发 .NetCore 插件列表
    .net core 服务生命周期
    从 Asp.Net Core 2.2 迁移到 3.0 的方案
    CSRedisCore 介绍
    Entity Framework 命令
    DataAnnotations 模型配置
    依赖注入学习(理论)
  • 原文地址:https://www.cnblogs.com/lokiii/p/10016365.html
Copyright © 2011-2022 走看看