题目大意:n种卡牌,每种卡牌被抽到的概率依次为P1,P2,,,Pn,抽一次最多抽到一张,最少0张。问抽满n种卡的次数的期望。
用容斥原理来做,先单独考虑,再减去重复的。比如有两种卡牌A,B,分别为p1,p2,抽到A牌的期望为1/p1,抽到B牌的期望为1/p2,然而抽A牌时会有对B牌的重复,抽B牌亦然。根据容斥原理,减去两者的并部分(这个并部分似乎在这里有些难以理解,对于概率论没学好的我。。。),这个并部分即抽到A或B的期望。即E=E1+E2-E(12)=1/p1 + 1/p2 - 1/(p1+p2)。
卡牌多了,奇加偶减。
AC代码:
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<iostream>
4
5 using namespace std;
6
7 double a[30];
8
9 double solve(int x)
10 { int n=(1<<x)-1; //二进制枚举
11 double sum=0;
12 for(int j=1;j<=n;j++)
13 {
14 int flag=0;
15 double sum2=0;
16 for(int i=0;i<x;i++)
17 {
18 if(j&(1<<i))
19 {
20 flag++;
21 sum2+=a[i+1];
22 }
23 }
24 if(flag&1) sum+=1/sum2;
25 else sum-=1/sum2;
26 }
27 return sum;
28 }
29 int main()
30 { int n;
31 while(~scanf("%d",&n))
32 { for(int i=1;i<=n;i++)
33 scanf("%lf",&a[i]);
34 double sum=solve(n);
35 printf("%.5f
",sum);
36 }
37
38
39
40 return 0;
41 }
另一种做法:概率dp
像状压DP一样,1表示已经取到了这种卡,0表示还没。
先看个例子,假设有10种卡,每种卡片被抽到的概率均为0.1,dp分析,假如我们已经抽到了k种卡片,那么再抽到一种新的卡片(第k+1种)的概率即为(10-k)/10,再抽到这种卡片的期望次数即为10/(10-k)。
所以,dp[k+1] = dp[k] + 10/(10-k);
当然,本题概率并不均等,还可能抽一次,毛都没有。
上面的式子也是化简后的式子,因为还需考虑是哪k种卡片,第k+1种又是哪一种。
期望一般逆推:
dp[k]=sum{dp[k+1]*P(k->k+1)}+P(n-k)
设dp[(1<<n)-1]为0,这样得出的答案与原来的状态呈反序,好强啊。
代码:
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 #include <cstdio> 5 using namespace std; 6 const int maxn = 20; 7 double dp[1<<maxn], p[maxn]; 8 int main() 9 { 10 int n; 11 while(~scanf("%d", &n)) 12 { 13 double cur = 0; 14 for(int i = 0; i < n; i++) 15 { 16 scanf("%lf", &p[i]); 17 cur += p[i]; 18 } 19 20 int last = (1 << n)-1; 21 dp[last]=0; 22 for(int i = last-1; i >= 0; i--) 23 { 24 double temp = 1-cur; //抽到空的概率 25 double k=0; 26 for(int j = 0; j < n; j++) 27 { 28 if((1<<j)&i) temp += p[j]; 29 else k += dp[i|(1 << j)]*p[j]; // 30 } 31 dp[i] = k/(1-temp)+1.0/(1-temp); 32 33 } 34 printf("%.5f ", dp[0]); 35 } 36 return 0; 37 }