测试地址:Card Collector
题目大意:
n
n
张牌,每次有的概率抽到第
i
i
张牌,问抽到过所有的牌所需的期望次数。
做法:本题需要用到Min-Max容斥。
很久之前我写过这题的状压DP写法,那个做法时间复杂度为,空间复杂度为
O(2n)
O
(
2
n
)
,而今天本人学会了一种新的做法:Min-Max容斥,这个做法比状压DP更加优美一些。
Min-Max容斥,又称最值反演,是指下面这个式子:
max{S}=∑T∈S(−1)|T|+1min{T}
max
{
S
}
=
∑
T
∈
S
(
−
1
)
|
T
|
+
1
min
{
T
}
其中
S,T
S
,
T
为集合,
max{S},min{S}
max
{
S
}
,
min
{
S
}
表示集合
S
S
的最大元素和最小元素。先别急着质问这个式子有什么卵用,我们先看看这个式子是怎么来的。
尝试证明右边等于左边。令,我们有一个关于集合
T
T
的映射,定义为:若集合
T
T
中包含,则
f(T)
f
(
T
)
就是
T
T
去掉后的集合,否则
f(T)
f
(
T
)
就是
T
T
加上后的集合。显然这个映射有这样一个性质:
f(f(T))=T
f
(
f
(
T
)
)
=
T
,那么
T
T
和就是一一对应的关系。除去空集和
{x}
{
x
}
两个集合的对应,其它的对应关系中,两个集合的大小正好差
1
1
,而它们的最小值都相同,所以根据上面的式子,它们相互抵消。而空集没有最小值,所以整个右边式子的值就等于这个集合的贡献:
x
x
,即。
说了这么多,这个式子在这题中有什么用呢?Min-Max容斥有一个非常重要的推论:
E[max{S}]=∑T∈S(−1)|T|+1E[min{T}]
E
[
max
{
S
}
]
=
∑
T
∈
S
(
−
1
)
|
T
|
+
1
E
[
min
{
T
}
]
其中
E[x]
E
[
x
]
表示
x
x
的期望,证明应该显然。而这个式子更常用的意义是这样的:给中每个元素随机赋值,表示这个元素第一次被取到的时间,那么
E[min{S}]
E
[
min
{
S
}
]
的意义就变成
S
S
中第一个被取的元素的期望被取时间,的意义就变成
S
S
中最后一个被取的元素的被取期望时间,也就是中所有元素都被取过所需的期望时间。我们发现这个时间就相当于取的次数,所以也就是期望次数。
这个推论在这题中就非常有用了,因为本题中
E[min{S}]=1∑i∈Spi
E
[
min
{
S
}
]
=
1
∑
i
∈
S
p
i
,所以我们只需
O(2n)
O
(
2
n
)
枚举集合即可算出
E[max{S}]
E
[
max
{
S
}
]
,空间复杂度也很小(
O(n)
O
(
n
)
),可以说是比状压DP优美很多了。
以下是本人代码:
#include <bits/stdc++.h>
using namespace std;
int n;
double p[25],ans;
void solve(int step,int cnt,double totp)
{
if (step>n)
{
if (!cnt) return;
double f=(cnt%2)?1.0:-1.0;
ans+=f/totp;
return;
}
solve(step+1,cnt,totp);
solve(step+1,cnt+1,totp+p[step]);
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;i++)
scanf("%lf",&p[i]);
ans=0.0;
solve(1,0,0.0);
printf("%.6lf\n",ans);
}
return 0;
}