KunKun的征途

明天的明天,你还会送我水晶之恋吗?

导航

[SGU495] Kids and Prizes (概率dp)

Posted on 2015-06-04 23:51  西域小车  阅读(222)  评论(0)    收藏  举报

题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=495

题目大意:有N个盒子,里面都放着礼物,M个人依次去选择盒子,每人仅能选一次,如果里面有礼物则将礼物取出来,把空盒子放回原位,若没有礼物,则把空盒子放回原位。求礼物被拿走的个数的数学期望。

 

令 x[i] 代表第i个人拿到的礼物的个数,即值为0或1。

那么,N个人拿到的礼物的个数为 X = Sigma(X[i])。

因此 E[X] = E[Sigma(X[i])] = Sigma(E[X[i]])

其中,X[i]服从两点分布,即E[X[i]] = P(i)。

 

定义状态f[i]代表第i个人能够抓到礼物的概率,可以将样本空间划分为第i-1个人拿到了礼物和第i-1个人没拿到礼物。

因此有 P(i) = P(i|~i-1) + P(i|i-1) 即 f[i] = f[i-1]*(f[i-1]-1/n)+(1-f[i-1])*f[i-1]

化简得f[i] = f[i-1]*(1-1/n)。

进一步。。数学期望就可以用等比数列求和公式来做了。。。。。

有代码:

 1 ///#pragma comment(linker, "/STACK:102400000,102400000")
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <vector>
 6 #include <map>
 7 #include <set>
 8 #include <bitset>
 9 #include <cmath>
10 #include <numeric>
11 #include <iterator>
12 #include <iostream>
13 #include <cstdlib>
14 #include <functional>
15 #include <queue>
16 #include <stack>
17 #include <string>
18 #include <cctype>
19 using namespace std;
20 #define PB push_back
21 #define MP make_pair
22 #define SZ size()
23 #define ST begin()
24 #define ED end()
25 #define CLR clear()
26 #define ZERO(x) memset((x),0,sizeof(x))
27 typedef long long LL;
28 typedef unsigned long long ULL;
29 typedef pair<int,int> PII;
30 const double EPS = 1e-8;
31 
32 const int MAX_N = 100000+100;
33 
34 double f[MAX_N];
35 int N,M;
36 
37 int main() {
38     while( ~scanf("%d%d",&N,&M) ) {
39         f[1] = 1.0;
40         double ans = 1.0;
41         for( int i=2;i<=M;i++ ){
42             f[i] = (1.0-f[i-1])*f[i-1] + f[i-1]*( f[i-1]-1.0/N );
43             ans += f[i];
44         }
45         printf("%.11f\n",ans);
46     }
47     return 0;
48 }