题目描述
小强需要抽取n个随机数,第i个随机数的抽取区间是[Li,Ri],即这个数是Li,L(i+1),…,Ri,这Ri-Li+1个正整数中的一个,在这个区间中随机到每个数字的概率相同,问这n个随机数的最小值的期望是多少?
----------------------------------------------------------------------------------------------------
输入描述
第一行,一个正整数n。
第二行,n个正整数L1,L2,L3,…,Ln。
第三行,n个正整数R1,R2,R3,…,Rn。
1<=n<=2000,1<=Li<=Ri<=2000
输出描述
一行一个实数表示答案,浮点误差精度为6位(1e-6),fabs(stdvalue-yourvalue)/max(1.0,fabs(stdvalue)<1e-6均正确。
----------------------------------------------------------------------------------------------------
输入
2
1 2
3 3
输出
1.83333333
说明
最小值为1时,两个随机数有(1,2),(1,3)两种情况,概率为2/6.
最小值为2时,两个随机数有(2,2),(2,3),(3,2)两种情况,概率为3/6.
最小值为3时,两个随机数有(3,3)两种情况,概率为1/6.
最小值的期望为1*2/6+2*3/6+3*1/6=1.83333333
----------------------------------------------------------------------------------------------------
题解
这道题比较考验数学基础,具体举例进行分析
2
1 2
3 4
此时依次从下往上分析1、2、3、4最小出现的概率。
- 分析1:
当第一列1出现时,第二列随便选什么都成立,概率就为第一列1出现的概率p=1/3=3/9,期望E(1)=1*p=3/9。 - 分析2:
第一列第二列都可能出现2,两列结合起来出现2的概率p1=(1-(1-1/3)(1-1/3))。
解释:要统计2出现的各种情况,不容易,可以先计算2在两列中都不出现的概率,为(1-1/3)(1-1/3),再用1减去这个不出现的概率,就是出现的概率。但是这里忽略了一个重要的问题就是,1不能和2同时出现,因为这样2就不是最小的了。
又注意到只要1存在于选择的数字中,2就不可能是最小的,所以可以先假设1不存在于第一列中,那么此时2出现的概率p2=(1-(1-1/2)(1-1/3))。
现在又返回看总的情况,1不出现在所有选项中的概率p3=(第一列不是1个选择个数)X(第二列不是1的选择的个数)/(所有可选择的个数)。
所以最后总的算起来,2出现且2为最小值的概率p=p2*p3=(1-(1-1/2)*(1-1/3))*((2*3)/(3*3))=4/9,期望E(2)=2*p=8/9。 - 分析3:情况和分析2同理,p=2/9,E(3)=3*p=2/3。
- 分析4:因为只要有一列的所有数小于4,无论如何选取,4都不可能为最小的数,所以p=0,E(4)=0。
最后答案是E=E(1)+E(2)+E(3)+E(4)=1.8889。
数学推理完成,编写代码
代码
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <unordered_set>
#include <sstream>
#include <unordered_map>
#include <fstream>
#include <iostream>
#include <map>
#include <iostream>
#include <vector>
using namespace std;
void main()
{
string test("2\r1 2\r3 4\r");
stringstream cin(test);
int n = 0;
cin >> n;
vector<int> l(n);
vector<int> r(n);
int maxr = 0;
int minl = INT_MAX;
for (int i = 0; i < n; i++)
{
cin >> l[i];
minl = min(minl, l[i]);
}
for (int i = 0; i < n; i++)
{
cin >> r[i];
maxr = max(maxr, r[i]);
}
//处理输入数据完成
double ans = 0;
for (int val = minl; val <= maxr; val++)
{
vector<int> appear;
for (int i = 0; i < n; i++)
{
if (val >= l[i] && val <= r[i])
{
appear.push_back(i);//判定哪些数字可能成为最小值
}
else if (val > r[i])//如果此数字已经不可能成为最小值,直接输出之前计算的答案
{
cout << ans;
return;
}
}
double p = 1;
int child = 1;
int parent = 1;
for (auto index : appear)
{
p *= 1 - 1.0 / (r[index] - val + 1);
child *= r[index] - val + 1;
parent *= r[index] - l[index] + 1;
}
p = (1 - p)*child/parent;//计算某个值可能出现的概率
ans += p * val;//计算期望,并累加
}
cout << ans;
}