给出
n
,
s
≤
1
e
3
n,s\leq1e3
n,s≤1e3存在
n
n
n种漏洞,而且它们等概率分布在
s
s
s个不同的系统中。花费一天的代价可以发现一个漏洞,但是这个漏洞可能是出现过的,要求发现
n
n
n种漏洞并且全部出现在
s
s
s个系统中的期望天数。
期望dp的特点是倒推。考虑
f
i
,
j
f_{i,j}
fi,j是发现
i
i
i种漏洞并且出现在
j
j
j个系统到最终状态的概率。
f
n
,
s
=
0
f_{n,s}=0
fn,s=0,并且显然有转移
f
i
,
j
=
(
i
n
∗
j
s
)
f
i
,
j
+
(
n
−
i
n
∗
j
s
)
f
i
+
1
,
j
+
(
i
n
∗
s
−
j
s
)
f
i
,
j
+
1
+
(
n
−
i
n
∗
s
−
j
s
)
f
i
+
1
,
j
+
1
+
1
f_{i,j}=(\frac{i}{n}*\frac{j}{s})f_{i,j}+(\frac{n-i}{n}*\frac{j}{s})f_{i+1,j}+(\frac{i}{n}*\frac{s-j}{s})f_{i,j+1}+(\frac{n-i}{n}*\frac{s-j}{s})f_{i+1,j+1}+1
fi,j=(ni∗sj)fi,j+(nn−i∗sj)fi+1,j+(ni∗ss−j)fi,j+1+(nn−i∗ss−j)fi+1,j+1+1。化简消去右边的
f
i
,
j
f_{i,j}
fi,j即可。
#include<cstdio>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=1e3+7;
double f[N][N];
int main() {
int n,s;
scanf("%d%d",&n,&s);
f[n][s]=0.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-i)*j*f[i+1][j]+i*(s-j)*f[i][j+1]+(n-i)*(s-j)*f[i+1][j+1]+n*s)/(n*s-i*j);
}
}
printf("%.4f\n",f[0][0]);
return 0;
}