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 }