概率计算:P(某set) =
令: 和
现在考虑:
1.考虑某个集合,再加一个概率为Pi的朋友后能不能使总概率提高。
即: 由公式可知, 如果 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 ;
}