【HDU4336】Card Collector(Min-Max容斥)

题面

Vjudge

题解

原来似乎写过一种状压的做法,然后空间复杂度很不优秀。
今天来补一种神奇的方法。


给定集合 S S ,设max{S} S S 中的最大值,min{S}为集合 S S 中的最小值。
那么我们可以得到:
max{S}=TS(1)|T|min{T}
证明的话,大概就是如果你钦定一个最小值,并且它强制出现,
如果枚举所有子集,不难证明除了最大值之外,任何一个数的出现次数都是 2k 2 k 的形式。
并且子集大小的奇偶性一一对应。因此,除了最大值之外,任何一个值的贡献全部会互相抵消,最后剩下的值就只有最大值。

对于期望而言这样做也是正确的。


回到这道题目,我们 max{S} m a x { S } 表示集合中最晚出现的元素, min m i n 同理。
E(max{S}) E ( m a x { S } ) 表示出现时间的期望。
那么我们要求的是 E(max{ E ( m a x { 全集 }) } ) ,那么利用 minmax m i n − m a x 容斥,有:
E(max{S})=TS(1)TE(min{T}) E ( m a x { S } ) = ∑ T ⊆ S ( − 1 ) T E ( m i n { T } )
E(min{T})=1iTpi E ( m i n { T } ) = 1 ∑ i ∈ T p i
那么枚举子集,直接 dfs d f s 实现就好了

#include<cstdio>
int n;
double p[20],ans;
void dfs(int x,double e,int opt)
{
    if(x>=n){if(e>1e-7)ans+=opt/e;return;}
    dfs(x+1,e,opt);dfs(x+1,e+p[x],-opt);
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=0;i<n;++i)scanf("%lf",&p[i]);
        ans=0;dfs(0,0,-1);
        printf("%.6lf\n",ans);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值