题目描述
题意:s个系统n种bug,每天找出一个bug,种类的概率是1/n,系统的概率是1/s。问:每个系统至少找出一个bug;每种类的bug都被找出。的期望天数(0<n, s<=1000)、
题解
这道题目一共有两个维度,bug个系统,这了对应了两个状态。
我们设f[i][j]为i个bug,s个系统,还需要期望的步数。我们要采用逆推。(逆推的原因就在于状态0也在考虑范围内,往前访问会造成下标越界)。
一共分为如下情况:
- bug不出现,系统出现。对应了f[i][j+1],p=s×ni×(s−j)
- bug出现,系统不出现。对应了f[i+1][j],p=s×n(n−i)×j
- bug出现,系统出现。对应了f[i+1][j+1],p=s×n(n−i)×(s−j)
- bug不出现,系统不出现。对应了f[i][j],p=s×ni×j
可以很容易得到状态转移方程:
f[i][j]=f[i][j+1]×s×ni×(s−j)+f[i+1][j]×s×n(n−i)×j+f[i+1][j+1]×s×n(n−i)×(s−j)+f[i][j]×s×ni×j+1
然后移项一下就可以辣~
#include <iostream>
#include <cstdio>
using namespace std;
int n, s;
double f[3000][3000];
int main(void)
{
cin>>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) {
double val1 = 1.0 * f[i+1][j] * (n-i) * j / s / n;
double val2 = 1.0 * f[i][j+1] * i * (s-j) / s / n;
double val3 = 1.0 * f[i+1][j+1] * (n-i) * (s-j) / s / n;
double val4 = 1.0 - 1.0 * i * j / s / n;
f[i][j] = 1.0*(val1+val2+val3+1)/val4;
}
printf("%.4f\n", f[0][0]);
return 0;
}