题意:
Ivan每天可以收集一个bug,每个bug属于某个类别和某个子系统,现求收集n种类别和s个子系统的期望天数。
比如bug1属于类别1子系统1,bug2属于类别1子系统2,那么就收集到了1个类别和2个子系统的bug。
题解:
f[i][j]表示已经有i个类别j个子系统的期望天数,那么当前这天找的bug有四种情况:
1.Bug属于已有的类别,已有的子系统,即f[i][j]−>f[i][j]f[i][j] -> f[i][j]f[i][j]−>f[i][j], 概率i/n∗j/si/n * j/si/n∗j/s
2.Bug属于没有的类别,已有的子系统,即f[i−1][j]−>f[i][j]f[i - 1][j] -> f[i][j]f[i−1][j]−>f[i][j], 概率(1−i/n)∗j/s(1 - i/n) * j/s(1−i/n)∗j/s
3.Bug属于已有的类别,没有的子系统,即f[i][j−1]−>f[i][j]f[i][j - 1] -> f[i][j]f[i][j−1]−>f[i][j], 概率i/n∗(1−j/s)i/n * (1 - j/s)i/n∗(1−j/s)
4.Bug属于没有的类别,没有的子系统,即f[i−1][j−1]−>f[i][j]f[i - 1][j - 1] -> f[i][j]f[i−1][j−1]−>f[i][j], 概率(1−i/n)∗(1−j/s)(1 - i/n) * (1 - j/s)(1−i/n)∗(1−j/s)
故f[i][j]=i/n∗j/s∗f[i][j]+(1−i/n)∗j/s∗f[i−1][j]+i/n∗(1−j/s)∗f[i][j−1]+(1−i/n)∗(1−j/s)∗f[i−1][j−1]f[i][j] = i/n * j/s * f[i][j] + (1 - i/n) * j/s * f[i - 1][j] + i/n * (1 - j/s) * f[i][j - 1] + (1 - i/n) * (1 - j/s) * f[i - 1][j - 1]f[i][j]=i/n∗j/s∗f[i][j]+(1−i/n)∗j/s∗f[i−1][j]+i/n∗(1−j/s)∗f[i][j−1]+(1−i/n)∗(1−j/s)∗f[i−1][j−1]
-> f[i][j]=(n∗s+(n−i)∗j∗f[i−1][j]+n∗(s−j)∗f[i][j−1]+(n−i)∗(s−j)∗f[i−1][j−1])/(n∗s−i∗j)f[i][j] = (n * s + (n - i) * j * f[i - 1][j] + n * (s - j) * f[i][j - 1] + (n - i) * (s - j) * f[i - 1][j - 1])/(n * s - i * j)f[i][j]=(n∗s+(n−i)∗j∗f[i−1][j]+n∗(s−j)∗f[i][j−1]+(n−i)∗(s−j)∗f[i−1][j−1])/(n∗s−i∗j)
我们所求的答案为f[n][s],但是这里i=n,j=si = n, j = si=n,j=s会使分母(n∗s−i∗j)(n * s - i * j)(n∗s−i∗j)为0,故要倒着推。
令f[n][s]=0f[n][s] = 0f[n][s]=0, 递推公式为f[i][j]=(n∗s+(n−i)∗j∗f[i+1][j]+i∗(s−j)∗f[i][j+1]+(n−i)∗(s−j)∗f[i+1][j+1])/(n∗s−i∗j)f[i][j] = (n * s + (n - i) * j * f[i + 1][j] + i * (s - j) * f[i][j + 1] + (n - i) * (s - j) * f[i + 1][j + 1]) / (n * s - i * j)f[i][j]=(n∗s+(n−i)∗j∗f[i+1][j]+i∗(s−j)∗f[i][j+1]+(n−i)∗(s−j)∗f[i+1][j+1])/(n∗s−i∗j), 所求答案为f[0][0]f[0][0]f[0][0]。
代码:
const int MAX = 1e3 + 10;
int n, s;
double f[MAX][MAX];
int main() {
scanf("%d%d", &n, &s);
f[n][s] = 0;
for (int i = n; i >= 0; i--)
for (int j = s; j >= 0; j--) {
if (i == n && j == s)continue;
f[i][j] = (n * s + (n - i) * j * f[i + 1][j] + i * (s - j) * f[i][j + 1] + (n - i) * (s - j) * f[i + 1][j + 1]) / (n * s - i * j);
}
printf("%.4lf\n", f[0][0]);
return 0;
}