码迷,mamicode.com
首页 > 其他好文 > 详细

luogu P3175 [HAOI2015]按位或

时间:2019-01-17 23:45:22      阅读:211      评论:0      收藏:0      [点我收藏+]

标签:print   std   mat   its   sum   clu   inf   ref   inline   

传送门

如果每个位置上的数字的意义是这个位置被加进集合的最早时间,那么我们要求的就是集合中最大数的期望,使用Min-Max容斥,\(E(max(S))=\sum_{T\subset S}(-1)^{|T|+1}E(min(T))\),这里的\(E(min(T))\)是集合中加进数字的期望时间,根据题意,加进一个集合数字概率为\(\sum_{s\cap T\ne\emptyset}P_s\),对应的期望,也就是\(E(min(T))=\frac{1}{\sum_{s\cap T\ne\emptyset}P_s}\)

但是\(\sum_{s\cap T\ne\emptyset}P_s\)不是很好求,可以转化成\(1-\sum_{s\cap T=\emptyset}P_s\),也就是\(1-\sum_{s\subset ?_{S}T}P_s\),高位前缀和即可

#include<bits/stdc++.h>
#define LL long long
#define il inline
#define re register
#define db double

using namespace std;
const int N=(1<<20)+10;
il int rd()
{
    int x=0,w=1;char ch=0;
    while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*w;
}
int n,nn;
db p[N],ans,h[N];

int main()
{
    n=rd();
    nn=(1<<n)-1;
    int ff=0;
    for(int i=0;i<=nn;++i)
    {
        scanf("%lf",&p[i]);
        if(p[i]>1e-8) ff|=i;
    }
    if(ff^nn) return puts("INF"),0;
    for(int i=1;i<=nn;i<<=1)
        for(int j=0;j<=nn;++j)
            if((j&i)==i) p[j]+=p[j^i];
    h[0]=1;
    for(int i=0;i<=nn;++i)
    {
        h[i]=-h[i^(i&(-i))];
        if(fabs(1-p[nn^i])>1e-8)ans+=h[i]*1/(1-p[nn^i]);
    }
    printf("%.8lf\n",ans);
    return 0;
}

luogu P3175 [HAOI2015]按位或

标签:print   std   mat   its   sum   clu   inf   ref   inline   

原文地址:https://www.cnblogs.com/smyjr/p/10285329.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!