Codeforces Round #253 Div2 D.Andrey and Problem 概率+贪心

时间:2021-10-15 21:47:05

概率计算:P(某set) = Codeforces Round #253 Div2 D.Andrey and Problem 概率+贪心

令:Codeforces Round #253 Div2 D.Andrey and Problem 概率+贪心  和  Codeforces Round #253 Div2 D.Andrey and Problem 概率+贪心

现在考虑:

1.考虑某个集合,再加一个概率为Pi的朋友后能不能使总概率提高。

即:Codeforces Round #253 Div2 D.Andrey and Problem 概率+贪心 由公式可知, 如果 S < 1,则delta > 0,则可以加入这个朋友。

2.如果要加一个朋友有两个候选的,其概率分别为Pi,Pj,(设Pi < Pj)那么加哪个会更优呢?

Δi - Δj = P·pi·(1 - S) - P·pj·(1 - S) = P·(1 - S)·(pi - pj) > 0.  如果 S < 1 那么 pi > pj 时可以使 Δi - Δj  > 0,即P较大的那个带来的价值更高,所以优先选P大的那个。虽然这个

只是局部更优,但是用反证法可以证明是全局最优的。

所以由上述分析,以概率从大到小的方式逐步加入元素,因为由,很可能S<1,即可能加一个会更优,所以我们逐步加入,又由2,优先加最大的,所以从大到小加入能保证最优。

然后每加入一个都计算该种情况下的总概率,更新答案。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#define Mod 1000000007
using namespace std;
#define N 1000007 double a[];
std::vector<double> v; double calc(vector<double> v)
{
int len = v.size();
int i,j;
double res = 0.0;
for(i=;i<len;i++)
{
double tmp = v[i];
for(j=;j<len;j++)
{
if(i == j)
continue;
tmp *= (-v[j]);
}
res += tmp;
}
return res;
} int main()
{
int n,i,j;
while(scanf("%d",&n)!=EOF)
{
double maxi = -1.0;
for(i=;i<n;i++)
scanf("%lf",&a[i]);
sort(a,a+n);
v.clear();
for(i=n-;i>=;i--)
{
v.push_back(a[i]);
maxi = max(calc(v),maxi);
}
printf("%.10lf\n",maxi);
}
return ;
}