这个东西看起来挺冷门的,不过要是考的话到不会还真做不出来……
这东西也不是很复杂,本文应该不会太长吧……
我们现在有一个全集
U={a1,a2,a3,...,an}
我们设
min(S)=ai∈Sminai(集合里的最小值)
相应的
max(S)=ai∈Smaxai(集合里的最大值)
假设我们能很轻松地求出任意集合的
min(S) ,但是我们不会(或者很难)求出任意集合的
max(S) 。
Min-Max容斥就是通过一种奥妙重重的方式把,Min转换成Max(或者反之)。
结论:
max(S)=T⊆S∑(−1)∣T∣+1min(T)
为什么是正确的呢?
我们设
U 以内的元素互不相同,如果相同的话我们就以编号为序,不影响后续推导。
我们设
Ak 为
U 内元素
降序排序后排名第
k 的元素,也就是第
k 大。
设
min(S)=Ak 那么
S 有那些情况呢?
令
min(S)=A1,很明显只有一种可能那就是
S={A1}
所以贡献是
(−1)2A1=A1
最小的元素是
Ak ,那么集合内不能存在比
Ak 小的
Ak+1...n ,而只能存在
A1...k 。
Ak必然在
S内,剩下有
2k−1种选法。
通过人类智慧得知,这
2k−1种选法之中,有
2k−2种
∣S∣是偶数,有
2k−2种
∣S∣是奇数。
那么偶数的情况乘以
−1,奇数的情况乘以
1,刚好消掉了。
综上,除了
min(S)=max(S)的那一个
S,其余的贡献都消掉了。最后,贡献和是
max(S)。
当然也可以把
max 转换成
min ,公式是
min(S)=T⊆S∑(−1)∣T∣+1max(T) ,十分对称。
附:Min-Max容斥定理在期望下也成立。
也就是说
E(max(S))=T⊆S∑(−1)∣T∣+1E(min(T))
这是非常有用的,因为期望下的
max 和
min 是很难求的。
假设有
a,b 两个不相关变量,则
E(max(a,b))=max(E(a),E(b))。
例子:抛硬币,
a=b={0(50%)1(50%) ,则
E(a)=E(b)=21
那么
max(a,b)=⎩⎨⎧max(0,0)(25%)max(0,1)(25%)max(1,0)(25%)max(1,1)(25%) ,则
E(max(a,b))=0.75
但是
max(E(a),E(b))=0.5所以期望不能大力拆
max 或
min 。
第一眼看去很难把这道题和Min-Max容斥联想起来(目前而言)
由于或运算时每个位都是独立的,我们可以把每个位分开来看。
我们设
ak为第
k个二进制位变为
1的时间。
那么我们要求的就是
E(max(U))(
U为全集)。
如何求出
E(min(S))呢?
离散期望计算公式
E(x)=∑v∗P(v),意思就是(
∑值*对应概率)。
我们设
P(S)为选中集合
S的概率,
P′(S)为选中
S的子集的概率。(
U为全集)
那么
min(S)=k的概率就是:前k-1次选了
S的补集的子集,最后一次不能选
S的补集的子集。
得到
min(S)′s P(k)=P′(S⊕U)k−1(1−P′(S⊕U))
那么,
E(min(S))=k=1∑∞k∗P(k)=k=1∑∞k∗P′(S⊕U)k−1(1−P′(S⊕U))
设
P′(S⊕U)=p
=(1−p)k=1∑∞k∗pk−1
后面的式子就是等差*等比求和,错位相减:
A=[1∗1,2∗p,3∗p2...k∗pk−1...],求
Sum
Sum=1∗p0+2∗p1+3∗p2+...
整体乘
p得到:
p∗Sum=1∗p+2∗p+3∗p+...
两式相减得到:
(1−p)Sum=1∗p0+(2−1)p+(3−2)p2+...=1−p1−p∞
因为
0≤p<1 ,所以
p∞=0 ,得到
(1−p)Sum=1−p1
所以
E(min(S))=1−P′(S⊕U)1
我们的目标是要求出
E(min(所有集合)) ,为了完成这个,我们要求出
P′(所有集合) 。
我们知道
P′(S)=T⊆S∑P(T) ,肉眼可见枚举子集。
O(3n) 肯定是会TLE的,所以请使用
位运算卷积
Or 卷积的
DWT 相当于子集求和,那么直接上就好了。
CPP#include<algorithm>
#include<cstdio>
#define Maxn 1100000
using namespace std;
int n;
double a[Maxn];
int siz[Maxn];
int main()
{
scanf("%d",&n);n=(1<<n);
for (int i=0;i<n;i++)scanf("%lf",&a[i]);
for (int len=1;len<n;len<<=1)
for (int p=0;p<n;p+=len+len)
for (int i=p;i<p+len;i++)
a[i+len]+=a[i];
double ans=0;
for (int i=1;i<n;i++){
siz[i]=siz[i>>1]+(i&1);
double sav=(1-a[i^(n-1)]);
if (sav<1e-8){puts("INF");return 0;}
sav=1/sav;
ans+=(siz[i]&1) ? -sav:sav;
}printf("%.10lf",-ans);
return 0;
}
我们仍然考虑使用容斥(消去)的方法:
Kthmax(S)=T⊆S∑F(∣T∣)min(T)
仿照上面的证明方法来构造:
那么有只有不包含比它小的
n−p+1个元素时,
min(T)=x,有
p−1个元素可供随意选择,而且必然选择
x。
贡献系数是
i=1∑p−1(ip−1)F(i+1)。
我们要令这个
=[p=k],也就是
i=1∑p(ip)F(i+1)=[p=k−1]
接下来使用二项式反演,还不会的同学请见“炫酷反演魔术”。
二项式反演得到
F(p+1)=i=1∑p(−1)p−i(ip)[i=k−1]=(−1)p−k+1(k−1p)
所以
F(p)=i=1∑p(−1)p−i(ip)[i=k−1]=(−1)p−k(k−1p−1)
那么一开始的式子就变成了:
Kthmax(S)=T⊆S∑(−1)∣T∣−k(k−1∣T∣−1)min(T)
我们带入
k=1的情况,发现
1thmax(S)=T⊆S∑(−1)∣T∣−1(0∣T∣−1)min(T)=T⊆S∑(−1)∣T∣+1min(T)
正和上面的经典形式相同。
喜闻乐见的是,扩展Min-Max容斥也是在期望意义下成立的,即:
E(Kthmax(S))=T⊆S∑(−1)∣T∣−k(k−1∣T∣−1)E(min(T))
题意:每秒按固定概率出现物品,求收集到
k 个物品的期望时间。
这道题还是很有难度的,这个黑牌不亏(或者是我的dp太菜了……)
分析:我们设集合
S 为某些物品的集合,物品的权值为第一次出现时间。
那么
E(min(S)) 就是这些物品中有其中一个出现的期望时间。
每一次得到
S 中物品的概率是
i∈S∑pi,那么期望时间就是
i∈S∑pi1。
我们能求
E(min(S)) 了,我们再想想,
E(Kthmin(U)) (
U 是全集)不就相当于期望耗时吗?
我们令下文的
k=n−k+1 ,求的就是
E(Kthmax(U)) 了,同时在题目中看到,这里的
k<=11 。
套用上面的扩展Min-Max容斥,我们就得到了式子:
Ans=T⊆S∑(−1)∣T∣−k(k−1∣T∣−1)E(min(T))
但是这里的
n≤1000 不能直接
O(2n)统计……
我们观察发现,
m<=10000 ,一道数数题居然限制值域? 没准是复杂度和
m 有关的
dp。
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
总结:
Min-Max容斥,考察范围较窄,学过的基本一眼就能看出来(flag)
但是可以结合期望,集合求和dp优化或者容斥,二项式反演来考,所以难度还是挺大的。
况且近年来都喜欢出毒瘤数数题,这玩意以后可能会被出成没有这么模板的题目吧,期待ing~