• 洛谷 P3175 [HAOI2015]按位或


    题目分析

    与hdu4336 Card Collector相似,使用min-max容斥。

    (max(S))表示集合(S)中最后一位出现的期望时间。

    (min(S))表示集合(S)中最初一位出现的期望时间。

    由min-max容斥可得:

    (max(T)=sumlimits_{S subseteq T}(-1)^{|T|-1}min(S))

    考虑求每一个(min(S))

    一个很显然的暴力代码:

    	for(int i=0;i<(1<<n);i++){
    		double tot=0;
    		for(int j=0;j<(1<<n);j++)if(i&j)tot+=p[j];
    		Min[i]=tot; 
    	}
    

    我们考虑对于每一个集合(S),实质上只有与它没有交集的数对它没有贡献。

    那么我们可以用总贡献减去与它没有交集的数的贡献。

    即对于每一个数,只需要对它的补集的子集全部减去它的贡献即可。

    这个很显然能够(O(nlogn))计算出来。

    那么就做完啦。

    #include <bits/stdc++.h>
    using namespace std;
    int n;
    double p[(1<<20)+5],a[25];
    int main(){
    	scanf("%d",&n);
    	for(int i=0;i<(1<<n);i++){
    		double x;
    		scanf("%lf",&x);
    		p[((1<<n)-1)^i]+=x;
    		for(int j=0;j<n;j++)
    			if(i&(1<<j))a[j]+=x;
    	}
    	for(int i=0;i<n;i++)if(!a[i]){puts("INF");return 0;}
    	for(int j=0;j<n;j++)
    		for(int i=0;i<(1<<n);i++)
    			if(i&(1<<j))p[i^(1<<j)]+=p[i];
    	for(int i=0;i<(1<<n);i++)p[i]=1-p[i];
    	double ans=0;
    	for(int i=1;i<(1<<n);i++){
    		int f=(__builtin_popcount(i)&1)?1:-1;
    		ans+=f/p[i];
    	}
    	cout<<fixed<<setprecision(7)<<ans<<"
    ";
    }
    
  • 相关阅读:
    jdbc的入门学习
    java代码生成Excel文件3000条自定义属性的的域账户名
    java面试题
    node图片资源捉取
    运用node真机调试移动web项目
    node读取文件转换json文件
    微信小程序页面导航功能
    JavaScript值全等判断
    微信小程序海报生成功能
    JavaScript常用数组操作方法,包含ES6方法
  • 原文地址:https://www.cnblogs.com/Trrui/p/9990032.html
Copyright © 2020-2023  润新知