题目描述
一个箱子里面有n个黑球m个白球。你每小时都随机从箱子里面抽出两个小球,然后把这两个球都染成黑球,然后再放回去。问需要多少小时才能把所有小球变成黑色小球?输出期望值。
输入输出格式
输入格式
多组测试数据。
第一行,一个整数G,表示有G组测试数据。1 <= G <= 10
每组测试数据格式如下:
一行,两个整数,n和m。1 <=n,m<=47。
输出格式
共G行,每行一个实数。误差不能超过0.00001。
输入输出样例
输入样例
5
1 1
2 1
1 2
4 7
1 3
输出样例
1.0
1.5
2.0
13.831068977298521
3.4
题解
设$sum=n+m$,设$dp[i]$为有$i$个黑球的情况下,把所有球都变成黑色小球的期望值。
易得$dp[i]=dp[i]\times\frac{i(i-1)}{sum(sum-1)}+dp[i+1]\times(1-\frac{i(i-1)}{sum(sum-1)}-\frac{(sum-i)(sum-i-1)}{sum(sum-1)})+dp[i+2]\times\frac{(sum-i)(sum-i-1)}{sum(sum-1)}+1$
整理得$dp[i]=\frac{dp[i+1]\times(1-\frac{i(i-1)}{sum(sum-1)}-\frac{(sum-i)(sum-i-1)}{sum(sum-1)})+dp[i+2]\times\frac{(sum-i)(sum-i-1)}{sum(sum-1)}+1}{1-\frac{i(i-1)}{sum(sum-1)}}$
直接推即可。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
#include <iostream> #include <cstdio> #define MAX_N (47 + 5) #define MAX_M (47 + 5) #define BB(x) (((double)(x) / sum) * ((double)((x) - 1) / (sum - 1))) #define WW(x) (((double)(x) / sum) * ((double)((x) - 1) / (sum - 1))) #define BW(x, y) (1 - BB(x) - WW(y)) using namespace std; int G; int n, m, sum; double dp[MAX_N + MAX_M]; int main() { scanf("%d", &G); while(G--) { scanf("%d%d", &n, &m); sum = n + m; dp[sum] = dp[sum + 1] = 0; for(register int i = sum - 1, j = 1; i >= n; --i, ++j) { dp[i] = (dp[i + 1] * BW(i, j) + dp[i + 2] * WW(j) + 1) / (1 - BB(i)); } printf("%lf\n", dp[n]); } return 0; }