zoukankan      html  css  js  c++  java
  • Min-Max容斥

    这个是一个很有意思的东西可以将特殊集合在已知能求最小值或最大值的情况下 将另一者反演出来的算法。

    简单来说 如 我们求某个子集的最小值很容易求 但最大值很难求的情况下我们就可以利用这个容斥 或者说是反演 将最大值求出来。

    如:max(a,b)=a+b+c-min(a,b);max(a,b,c)=a+b+c-min(a,b)-min(a,c)-min(b,c)+min(a,b,c);

    显然 将所有数取相反数 发现最大值求最小值的公式与最小值求最大值的公式形式相同 所以我们只需要讨论一种即可。 #####形式

    记Max(S)表示集合S的最大值 Min(S)表示集合的最小值。

    有:$Max(S)=sumlimits_{Tsubset S,T eq phi}(-1)^{|T|-1}Min(T)$

    (看起来挺显然的。。和容斥差不多的样子。 #####prove: 证明我是不会写的 可以自己意会 毕竟不算难。 提示:可以考虑使用二项式反演来证明 或者 采用贡献法。 LINK:[dalao的证明](https://www.cnblogs.com/GXZlegend/p/11563330.html) 当然我觉得他第二个证明写的云里雾里的 可以自己考虑一下证明。

    从这个证明我们还可以得出K大值也是可以求出来的。

    记kMax(S)表示集合S的第k大值。

    $kMax(S)=sumlimits_{Tsubset S,|T|ge k}(-1)^{|T|-k}{|T|-1choose k-1}Min(T)$ #####应用:

    Min-Max容斥极其推广常用于解决"都出现的期望时间问题"。

    记ti表示第i个元素出现的时间。

    Max(S)表示S中t的最大值,即所有元素出现时间的最大值,即所有元素都出现的时间。

    Min(S)表示S中t的最小值,即所有元素出现时间的最小值,即至少有一个出现的时间。

    根据Min-Max容斥有 $Max(S)=sumlimits_{Tsubset,T eq phi}(-1)^{|T|-1}Min(T)$

    对左右两边同时取期望 由于期望的线性,期望可以直接放在求和号里面。

    $E(Max(S))=sumlimits_{Tsubset,T eq phi}(-1)^{|T|-1}E(Min(T))$

    可以发现E(Min(T))求起来十分容易 当单位时间出现T中至少一个的概率为p,那么T中至少出现一个的概率时间为$frac{1}{p}$

    通过公式求Max(S) 即可求出所有元素都出现的期望时间了。

    如果只需要求出Max(U)的话,只需要计算每个自己对全集的贡献即可。

    如果要对所有的S求Max(S)的话,一种较快的方法是用按位分治来代替枚举子集。有两种常用写法,它们稍加处理就可以变成公式中的形式。 一: ``` for(i = 1 ; i < (1 << n) ; i <<= 1) for(j = 0 ; j < (1 << n) ; j ++ ) if(j & i) f[j] -= f[i]; ``` 此时系数为$(-1)^{|S|-|T|}$ 二: ``` for(i = 1 ; i < (1 << n) ; i <<= 1) for(j = 0 ; j < (1 << n) ; j ++ ) if(j & i) f[j] = f[i] - f[j]; ``` 此时系数为$(-1)^{|T|}$.

    上例题:

    LINK:[HDU4336](http://acm.hdu.edu.cn/showproblem.php?pid=4336)

    有 n 种卡片,每次购买有 pi 的概率买到第 i 种,求使得每种都买到的期望购买次数。

    $nleq 20$

    一上例题就蒙蔽 才知道自己期望学的啥也不是。。

    我们考虑如何求出一个集合中至少有一个卡片出现的期望时间(这里的次数即时间嘛。。

    期望个数=时间*概率 那么期望时间=个数/概率。。我也不知道这个算的对不对。。

    于是我们可以在线性的时间内算出来上述的至少有一个卡片出现的期望时间了 采用Min-Max反演 反演出最大的那个时间即可。

    随便写了发现 发现过了。。 ``` const int MAXN=30; int n; db p[MAXN],ans; int main() { freopen("1.in","r",stdin); while(scanf("%d",&n)==1) { for(int i=1;i<=n;++i)scanf("%lf",&p[i]); ans=0; for(int j=1;j<(1<HA省2015年出这种题是打算然这道题都爆零么...

    这道题是求二进制下每一位都出现的期望时间 也就是求得还是Max(S)

    我们只需要求出全集中最晚出现的期望时间即可得到答案。

    还是考虑容斥 考虑一下Min(T)怎么计算 一个集合中最早出现的某个二进制位的期望时间。

    我们需要求出T中所有二进制位可能出现的概率p的和 1/p就是时间了 和上题一样。

    直接暴力计算所有和T与不为0的集合的概率和 这样复杂度为$3^n$

    考虑一下补集转换 就交为0的区间的概率和 显然是一个大区间包含了若干个小区间 交都为0.

    求子集和 我们可以采用FWT的或第一步来求与的子集和 复杂度为$ncdot 2^n$

    注意判断无解的情况。 ``` const int MAXN=21; int n,maxx,cnt[1<>1; for(int j=0;j<=maxx;j+=len) for(int i=0;i

  • 相关阅读:
    Oracle和SQLServer中实现跨库查询
    sqlserver中创建链接服务器
    无法从命令行或调试器启动服务,必须首先安装Windows服务(使用installutil.exe),然后用ServerExplorer、Windows服务器管理工具或NET START命令启动它
    Win8系统运行程序提示“占位程序接收到错误数据”的解决方法
    设计模式——简单工厂模式
    设计模式——单例模式
    设计模式——观察者模式
    三一集团提前批java面经
    form表单传到后端的数据乱码
    Failed to obtain the JDBC Connection + Access denied for user 'XXX'@'localhost' (using password: YES)
  • 原文地址:https://www.cnblogs.com/chdy/p/12456940.html
Copyright © 2011-2022 走看看