Min-Max容斥及其推广和应用

概念

Min-Max容斥,又称最值反演,是一种对于特定集合,在已知最小值或最大值中的一者情况下,求另一者的算法。

例如:

max(a,b)=a+bmin(a,b)max(a,b,c)=a+b+cmin(a,b)min(a,c)min(b,c)+min(a,b,c)

显然,将所有数取相反数,易知用最大值求最小值的公式与用最小值求最大值的公式形式相同。以下只讨论用最小值求最大值的方法。

形式

Max(S) 表示集合 S 的最大值,Min(S) 表示集合 S 的最小值,则:

Max(S)=TS,Tϕ(1)|T|1Min(T)

推导

设存在一个以集合大小为自变量的函数 f 满足 Max(S)=TS,Tϕf(|T|)Min(T)

S 中元素从大到小排列为 x1,x2,...,xm ,则对于 xi ,其在左侧的贡献为 [i=1] ,在右侧的贡献为 j=0i1(i1j)f(j+1)

若等式成立,则必有 [i=1]=j=0i1(i1j)f(j+1)

F(i)=[i+1=1] (即 [i=1]=F(i1) ),G(i)=f(i+1) ,则 F(i)=j=0i(ij)G(j)

进行二项式反演,得 G(i)=j=0i(1)ij(ij)F(j)=(1)i

f(i)=G(i1)=(1)i1

因此构造成立,故:

Max(S)=TS,Tϕ(1)|T|1Min(T)

另一种证明

考虑等式右侧,记最小值为 xi ,则:

  • i=1 时,贡献为 1
  • i1 时,则 x1 有选和不选两种方案,这两种方案一一对应且系数恰为相反数,故总贡献为 0

故右侧的总和就是 x1=Max(S)

推广

kMax(S) 表示集合 S 的第 k 大值,则:

kMax(S)=TS,|T|k(1)|T|k(|T|1k1)Min(T)

推导

设存在一个以集合大小为自变量的函数 g 满足 kMax(S)=TS,Tϕg(|T|)Min(T)

S 中元素从大到小排列为 x1,x2,...,xm ,则对于 xi ,其在左侧的贡献为 [i=k] ,在右侧的贡献为 j=0i1(i1j)g(j+1)

若等式成立,则必有 [i=k]=j=0i1(i1j)g(j+1)

F(i)=[i+1=k] (即 [i=k]=F(i1) ),G(i)=g(i+1) ,则 F(i)=j=0i(ij)G(j)

进行二项式反演,得 G(i)=j=0i(1)ij(ij)F(j)=(1)ik+1(ik1)

f(i)=G(i1)=(1)ik(i1k1)

因此构造成立,故:

kMax(S)=TS,|T|k(1)|T|k(|T|1k1)Min(T)

应用

Min-Max容斥及其推广常用于解决“都出现的期望时间”问题,处理方法:

ti 表示第 i 个元素的出现时间,则:

  • Max(S) 表示 St 的最大值,即所有元素出现时间的最大值,即所有元素都出现的时间;
  • Min(S) 表示 St 的最小值,即所有元素出现时间的最小值,即至少有一个出现的时间。

根据Min-Max容斥,有 Max(S)=TS,Tϕ(1)|T|1Min(T)

对左右同时取期望,由于线性,期望可以直接放到求和符号里面,即 E(Max(S))=TS,Tϕ(1)|T|1E(Min(T))

容易发现 E(Min(T)) 求起来十分容易:当单位时间出现 T 中至少一个的概率为 p ,则出现 T 中至少一个的期望时间为 1p

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

对于Min-kMax容斥同理。

写法

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

如果要对所有 SMax(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|

例题

[hdu4336]Card Collector

题目大意

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

1n20

题解

Min-Max容斥基础题,参见上面的 “应用” 部分。

对于本题,有 Min(S)=1iSpi ,然后套用 MinMax 容斥的公式即可。

时间复杂度 O(2n)

#include <cstdio>
#define N 1100010
int cnt[N];
double p[N] , f[N];
int main()
{
    int n , i , j;
    double ans;
    while(~scanf("%d" , &n))
    {
        ans = 0;
        for(i = 0 ; i < n ; i ++ ) scanf("%lf" , &p[1 << i]);
        for(i = 1 ; i < (1 << n) ; i ++ ) f[i] = f[i - (i & (-i))] + p[i & (-i)] , cnt[i] = cnt[i - (i & -i)] + 1;
        for(i = 1 ; i < (1 << n) ; i ++ ) ans += ((cnt[i] & 1) ? 1 : -1) / f[i];
        printf("%lf\n" , ans);
    }
    return 0;
}

[bzoj4036]按位或

题目大意

你初始有数字 0 ,每次操作会随机选择 [0,2n1] 的一个数字与你的数字进行按位或运算,选到数 i 的概率为 pi 。求使得你的数字变为 2n1 的期望操作次数。

1n20

题解

和上一题类似,问题转化为计算 Min(S) ,即需要求出所有与 S 有公共元素(取与不为 0 )的 p 之和。

正难则反,考虑求所有与 S 无公共元素的 p 之和,即 S 的补集 2n1S 的所有子集的 p 之和,使用按位分治来解决。

最后套公式计算即可。无解的判定通过判断是否某一位都存在一个 p0 的元素来处理。

时间复杂度 O(n×2n)

代码

#include <cstdio>
#include <algorithm>
using namespace std;
double p[1100010];
int cnt[1100010];
int main()
{
    int n , i , j;
    double ans = 0;
    scanf("%d" , &n);
    for(i = 0 ; i < (1 << n) ; i ++ ) scanf("%lf" , &p[i]);
    for(i = 1 ; i < (1 << n) ; i ++ ) cnt[i] = cnt[i - (i & -i)] + 1;
    for(i = 1 ; i < (1 << n) ; i <<= 1)
    {
        for(j = 0 ; j < (1 << n) ; j ++ )
            if((j & i) && p[j])
                break;
        if(j == (1 << n))
        {
            puts("INF");
            return 0;
        }
    }
    for(i = 1 ; i < (1 << n) ; i <<= 1)
        for(j = 0 ; j < (1 << n) ; j ++ )
            if(j & i)
                p[j] += p[j ^ i];
    for(i = 1 ; i < (1 << n) ; i ++ ) ans += ((cnt[i] & 1) ? 1 : -1) / (1 - p[(1 << n) - 1 - i]);
    printf("%.8lf\n" , ans);
    return 0;
}

[luogu4707]重返现世

题目大意

n 种物质,每单位时间会随机生成一种物质,生成第 i 种物质的概率为 pim 。求获得 k 种物质的期望时间。

1n10001m100001knpi 为整数且 i=1npi=mnk10

题解

获得 k 种物质,相当于求所有获得时间中第 nk+1 大的,问题转化为Min-kMax容斥问题。方便起见,以下令 q=nk+1 ,则有 1q11

由于 n1000 之大,使用前两道题的子集统计方法显然会直接暴毙。

思考:尽管我们的集合选取方案有 2n 种,但每种的 Min(S) 只和 iSpi 有关,因此状态数其实只有 m 种。

一个比较显然的思路是设 fi,j,l 表示前 i 种物质选出 j 种,凑齐 p=l 的方案数,然而数据范围过大,无法通过此题。

到此为止,我们还有一个条件没有用到:q11

考虑在已知 fi,j,l 后答案的计算,贡献为 (1)jq(j1q1)×ml×fi,j,l 。对于前面的部分,运用组合数公式,有:

(1)jq(j1q1)=(1)(j1)(q1)(j2q2)(1)(j1)q(j2q1)

fi,j,l 又有转移 fi,j,l=fi1,j,l+fi1,j1,lpi ,故:

(1)jq(j1q1)fi,j,l=(1)jq(j1q1)fi1,j,l+(1)(j1)(q1)(j2q2)fi1,j1,lpi(1)(j1)q(j2q1)fi1,j1,lpi

发现了什么?前面的系数只和 j 与计算答案时所用的 q 有关,因此设 gi,j,l,t 表示前 i 种物质选出 j 种,凑齐 p=l ,且最终计算时的 q=t 的系数乘以方案数。则有:

gi,j,l,t=gi1,j,l,t+gi1,j1,lpi,t1gi1,j1,lpi,t

我们所做的似乎都是无用功。但事实上,仔细观察就会发现 j 的一维已经没有用处,无论是转移还是最终答案都不需要用到 j

左右对 j 那一维求和,便有 hi,l,t 表示前 i 种物质选出若干种,凑齐 p=l ,且最终计算时的 q=t 的系数乘以方案数,则有:

hi,l,t=hi1,l,t+hi1,lpi,t1hi1,lpi,t

最终答案就是 i=1mhn,i,q×mi

时间复杂度 O(nmq) ,由于空间不足,需要使用滚动数组。

代码

#include <cstdio>
#include <cstring>
#define mod 998244353
typedef long long ll;
ll p[1010] , f[2][10010][11];
inline ll qpow(ll x , ll y)
{
    ll ans = 1;
    while(y)
    {
        if(y & 1) ans = ans * x % mod;
        x = x * x % mod , y >>= 1;
    }
    return ans;
}
int main()
{
    int n , t , m , i , j , k , d;
    ll ans = 0;
    scanf("%d%d%d" , &n , &t , &m) , t = n - t + 1;
    for(i = 1 ; i <= n ; i ++ ) scanf("%lld" , &p[i]);
    for(i = 1 ; i <= t ; i ++ ) f[0][0][i] = -1;
    for(d = i = 1 ; i <= n ; i ++ , d ^= 1)
    {
        memcpy(f[d] , f[d ^ 1] , sizeof(f[d]));
        for(j = p[i] ; j <= m ; j ++ )
            for(k = 1 ; k <= t ; k ++ )
                f[d][j][k] = (f[d][j][k] + f[d ^ 1][j - p[i]][k - 1] - f[d ^ 1][j - p[i]][k] + mod) % mod;
    }
    for(i = 1 ; i <= m ; i ++ ) ans = (ans + f[n & 1][i][t] * m % mod * qpow(i , mod - 2)) % mod;
    printf("%lld\n" , ans);
    return 0;
}
posted @   GXZlegend  阅读(2774)  评论(1编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
历史上的今天:
2017-09-21 【bzoj2506】calc 根号分治+STL-vector+二分+莫队算法
2017-09-21 【bzoj4917】Hash Killer IV 乱搞
2017-09-21 【bzoj2770】YY的Treap 权值线段树
2017-09-21 【bzoj4898】[Apio2017]商旅 Floyd+分数规划+Spfa
点击右上角即可分享
微信分享提示