题意:
有N(1<=N<=20)张卡片,每包中含有这些卡片的概率为p1,p2,````pN.
每包至多一张卡片,可能没有卡片。
容斥原理
有N(1<=N<=20)张卡片,每包中含有这些卡片的概率为p1,p2,````pN.
每包至多一张卡片,可能没有卡片。
求需要买多少包才能拿到所以的N张卡片,求次数的期望。
解析:
这题一看反应就是概率DP,没怎么想到容斥,设dp【i】 表示当前状态i到达目标状态的期望花费(每包一个花费),这时需要二进制进行状态压缩,如6 为110 表示 第0张卡片没有,第1张和第二张有,则 dp【(1<<n)-1】就是目标状态,(1<<n)-1=111111(n个1),其实这样二进制压缩就和容斥的原理差不多了
容斥:需要知道,当只有1个卡片时,其期望就是1/p[i]; 用位枚举就可以了
概率DP
#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;
const int N=1<<20;
double dp[N],p[25],p1;
int main()
{
int i,j,n,s,w;
double py,pw;
while(~scanf("%d",&n))
{
p1=1.0;
for(i=0; i<n; i++)
{
scanf("%lf",&p[i]);
p1-=p[i];
}
s=(1<<n)-1;
dp[s]=0;
for(i=s-1; i>=0; i--)
{
py=p1;
pw=1;
for(j=0;j<n;j++)
{
w=1<<j;
if(i&w) py+=p[j];
else pw+=p[j]*dp[i+w];
}
dp[i]=pw/(1.0-py);
}
printf("%lf\n",dp[0]);
}
return 0;
}
容斥原理
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
double p[22];
int main()
{
int n;
while(scanf("%d",&n)==1)
{
for(int i=0;i<n;i++)scanf("%lf",&p[i]);
double ans=0;
for(int i=1;i<(1<<n);i++)
{
int cnt=0;
double sum=0;
for(int j=0;j<n;j++)
if(i&(1<<j))
{
sum+=p[j];
cnt++;
}
if(cnt&1)ans+=1.0/sum;
else ans-=1.0/sum;
}
printf("%.5lf\n",ans);
}
return 0;
}