LightOJ 1342 Aladdin and the Magical Sticks [想法题]

题目链接 : http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=27050

------------------------------------------------------------------------------------------------------------

我们先考虑这个问题

有一堆牌 其中$n$张牌抽到后不放回 另$m$张牌抽到后放回

求每张牌都抽到过至少一次 需要的抽牌次数的期望

对于这个问题 我们显然可以列出期望的等式后转化为$dp$方程求解 复杂度$O(nm)$

------------------------------------------------------------------------------------------------------------

然而这个复杂度并不够优

这时 我们需要考虑到如果全部都是放回的话 复杂度只有$O(n + m)$ $($同样可以用$dp$求解$)$

如果我们把不放回的都看做放回的 那么一旦抽到不放回的 $($ 第一次抽到除外 $)$ 就不算这次的

于是不放回的只用在最后减去贡献即可

------------------------------------------------------------------------------------------------------------

由于不放回的牌的期望均为$1$ 放回的牌的期望也均为一个定值

因此再加上权值也是很容易的

//由于通过$dp$计算出来的值刚好是欧拉常数$γ$的前$n$项和

//所以就直接预处理出来对于每个$n$的$γ$即可

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <algorithm>
 5 using namespace std;
 6 const int N = 5010;
 7 double r[N];
 8 int t, n;
 9 double ans;
10 int main()
11 {
12     for(int i = 1; i <= 5000; ++i)
13         r[i] = r[i - 1] + 1.0 / i;
14     scanf("%d", &t);
15     for(int ca = 1; ca <= t; ++ca)
16     {
17         int x, y;
18         scanf("%d", &n);
19         ans = 0;
20         for(int i = 1; i <= n; ++i)
21         {
22             scanf("%d%d", &x, &y);
23             if(y == 1)
24                 ans += x;
25             else
26                 ans += r[n] * x;
27         }
28         printf("Case %d: %.7f\n", ca, ans);
29     }
30     return 0;
31 }

 

你可能感兴趣的:(LightOJ 1342 Aladdin and the Magical Sticks [想法题])