题目大意
有 (n) 个明星,每个明星有 (dfrac 1 n) 的概率被抽中,求充中 (n) 个明星的期望次数。
题解
设 (E(i)) 为抽到 (i) 个明星的期望次数,则 (E(i) = E(i-1) + sumlimits_{k=1}^{infty}k imes left(dfrac{i-1}{n}
ight)^{k-1} imes dfrac{n-i+1}{n}) 。
显然 (dfrac{i-1}{n} imes E(i) = dfrac{i-1}{n} imes E(i-1) + sumlimits_{k=1}^{infty}k imes left(dfrac{i-1}{n}
ight)^k imes dfrac{n-i+1}{n}) 。
两式相减得到
[egin{aligned}E(i) &= E(i-1) + sumlimits_{k=1}^{infty}left(dfrac{i-1}{n}
ight)^{k-1} \ &= E(i-1) + limlimits_{k o infty} 1 imes dfrac{1 - left( frac{i-1}{n}
ight)^k}{1 - frac{i-1}{n}} \ &= E(i-1) + dfrac{n}{n-i+1}end{aligned}
]
故 (E(n) = sumlimits_{i=1}^{n}dfrac{n}{i}) 。
#include <cstdio>
long long gcd(long long a, long long b) {
long long c;
while (b) {
c = a % b;
a = b;
b = c;
}
return a;
}
int n;
struct Frac {
long long a, b;
Frac(long long _a = 0, long long _b = 1) {
a = _a;
b = _b;
}
Frac operator + (Frac x) {
Frac res;
res.a = a * x.b + b * x.a;
res.b = b * x.b;
if (res.a) {
long long g = gcd(res.a, res.b);
res.a /= g;
res.b /= g;
} else {
res.b = 1;
}
return res;
}
} E;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
E = E + (Frac){n, i};
if (E.b == 1) {
printf("%lld", E.a);
return 0;
}
long long m = E.a / E.b, t1 = m, t2 = E.b, c1 = 0, c2 = 0;
E.a %= E.b;
while (t1) {
++c1;
t1 /= 10;
}
while (t2) {
++c2;
t2 /= 10;
}
for (int i = 1; i <= c1; ++i)
putchar(' ');
printf("%lld
%lld", E.a, m);
for (int i = 1; i <= c2; ++i)
putchar('-');
putchar('
');
for (int i = 1; i <= c1; ++i)
putchar(' ');
printf("%lld", E.b);
return 0;
}
另一种做法:
考虑逆推,设 (E(i) = E(i+1) imes dfrac{n-i}{n} + E(i) imes dfrac{i}{n} + 1 Longrightarrow E(i) = E(i+1) + dfrac{n}{n-i}) 。
考虑顺推,设 (E(i) = E(i-1) imes dfrac{n-i+1}{n} + E(i) imes dfrac{i}{n} + 1 Longrightarrow E(i) = E(i-1) + dfrac{n-i+1}{n-i})
显然顺推是错的,逆推是对的。
期望题逆推可能比顺推更简单 。
顺推做法可以参考这里 。