题目链接:http://codeforces.com/problemset/problem/513/C
题意:有n个公司,他们要竞标一个广告位,他们出的钱的金额在L[i]到R[i]之间,问你所有公司所出的钱中第二高的金额的期望值。(2 <= n <= 5 ,1 <= L[i],R[i] <=10000)
目前碰到概率和期望的题目简直毫无思路啊。。。现在的能力只能去硬着头皮看题解(感觉能彻懂题解都不错了。。)
解法(参考tourist的代码):可以用很暴力的方法来做,首先枚举第二高的金额(1~10000),然后枚举所有公司有哪几个公司出的钱达到了当前枚举的第二高金额(状态压缩,0表示该公司没达到,1表示达到了),如果达到的公司小于两个就跳出把,应为1个公司不管出多少钱都是第一高的金额。之后判断每个公司达到和不达到的状态。对于所有的公司而言,他们所能出的钱和当前枚举的金额(now)只有这3种状态,L <= R <= now,L <= now <= R,now <= L <= R。
对于达到第二高金额的公司,若L <= now,那么概率为(R - now + 1) / (R - L + 1),因为只考虑会出现第二高金额的部分嘛;对于未达到第二高金额的公司,若R > now - 1,那么概率为(now - 1 - L + 1) / (R - L + 1),因为要保证这个公司不会达到第二高金额;最后将所有的概率都加起来就是最后的答案了(这里不懂,为什么全部加起来就是期望了,期望不是 概率 * 值 吗。。。)
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn = 55;
int L[maxn],R[maxn];
int main()
{
int n;
while(~scanf("%d",&n))
{
double sum = 0;
for(int i = 0;i < n;i++)scanf("%d%d",L + i,R + i);
for(int now = 1;now <= 10010;now++)
{
for(int sta = 0;sta < (1 << n);sta++)
{
int cnt_1 = 0;
for(int i = 0;i < n;i++)
if(sta & (1 << i))
cnt_1++;
if(cnt_1 < 2)continue;
double res = 1.0;
for(int i = 0;i < n;i++)
{
int l = L[i];
int r = R[i];
double pro = 1.0;
if(sta & (1 << i)){//对于达到第二高金额的公司
if(l < now)l = now;
}else{//对于未达到第二高金额的公司
if(r > now - 1) r = now - 1;
}
if(l > r)//这种情况不可能的,break
{
res = 0.0;break;
}
int cur = r - l + 1;
res *= 1.0 * cur / (R[i] - L[i] + 1);
}
sum += res;
}
}
printf("%.15lf\n",sum);
}
}