版权声明:原创文章,转载要注明作者哦 https://blog.csdn.net/DYT_B/article/details/85297532
题目描述:戳这里
题解:
这题如果按照题意做看似非常不可解,但是有一个叫做Min-Max容斥的东西:
对于这题,Max就是答案,也就是
到
的期望步数。
Min就是对于当前的二进制位的集合,至少
到一位是1的期望步数。
那么接下来的问题就变成了求Min。
我们列出式子:
补集转换:
对U再取个补集:
那么就是求
的子集的P之和。
这可以直接用一个
的DP就可以预处理出来。
所以总的复杂度就是
。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int maxn=25,maxm=(1<<20)+5;
int n;
double ans,f[maxm];
double abs_(double x){if (x<0.0) return -x; return x;}
int main(){
scanf("%d",&n);
int now=0;
for (int i=0;i<(1<<n);i++) {
scanf("%lf",&f[i]);
if (abs_(f[i])>1e-7)
now=now|i;
}
if (now^((1<<n)-1)) {
printf("INF\n");
return 0;
}
for (int i=1;i<=n;i++)
for (int j=0;j<(1<<n);j++)
if (j&(1<<i-1)) f[j]+=f[j^(1<<i-1)];
for (int i=1;i<(1<<n);i++){
int sum=0;
for (int j=1;j<=n;j++) if (i&(1<<j-1)) sum++;
int x=i^((1<<n)-1);
if ((sum-1)%2==0) ans+=1.0/(1.0-f[x]); else ans-=1.0/(1.0-f[x]);
}
printf("%.10lf\n",ans);
return 0;
}