做法超级简单,先从小到大排序,然后从后向前扫,选上更优就选上,不然就 breakbreakbreak
证明。
反证法:假设选择集合不是后缀
假设现在有一个选择集合 SSS(存储的是下标),找到这个集合出现的空隙(即 i∉S,i−1∈Si \notin S,i-1\in Si∈/S,i−1∈S)。
令 T=∁S{i−1}T = \complement_S\{i - 1\}T=∁S{i−1}
令 f(P)=Π(1−xpi),g(P)=∑xpi1−xpi,a=xi,b=xi−1f(P) = \Pi(1 - x_{p_i}), g(P) = \sum \frac{x_{p_i}}{1 - x_{p_i}},a = x_i, b = x_{i - 1}f(P)=Π(1−xpi),g(P)=∑1−xpixpi,a=xi,b=xi−1
则有:a>ba > ba>b
容易得到计算答案的式子: f(P)∗g(P)f (P) * g (P)f(P)∗g(P)
即证 f(T⋃{i})∗g(T⋃{i})>f(T⋃{i−1})∗g(T⋃{i−1})f(T \bigcup \{i\}) * g(T \bigcup \{i\}) > f(T \bigcup \{i - 1\}) * g(T \bigcup \{i - 1\})f(T⋃{i})∗g(T⋃{i})>f(T⋃{i−1})∗g(T⋃{i−1})
即证 f(T)∗(1−a)∗(g(T)+a1−a)>f(T)∗(1−b)∗(g(T)+b1−b)f(T) * (1 - a) * (g (T) + \frac{a}{1-a}) > f(T) * (1 - b) * (g (T) + \frac{b}{1-b})f(T)∗(1−a)∗(g(T)+1−aa)>f(T)∗(1−b)∗(g(T)+1−bb)
即证 f(T)∗g(T)∗(1−a)+a1−a∗(1−a)∗f(T)>f(T)∗g(T)∗(1−b)+b1−b∗(1−b)∗f(T)f(T) * g (T) * (1 - a) + \frac{a}{1 - a} * (1 - a) * f (T) > f(T) * g (T) * (1 - b) + \frac{b}{1 - b} * (1 - b) * f (T)f(T)∗g(T)∗(1−a)+1−aa∗(1−a)∗f(T)>f(T)∗g(T)∗(1−b)+1−bb∗(1−b)∗f(T)
即证 f(T)∗g(T)∗(1−a)+a∗f(T)>f(T)∗g(T)∗(1−b)+b∗f(T)f(T) * g (T) * (1 - a) + a * f (T) > f(T) * g (T) * (1 - b) + b * f (T)f(T)∗g(T)∗(1−a)+a∗f(T)>f(T)∗g(T)∗(1−b)+b∗f(T)
即证 g(T)−g(T)∗a+a>g(T)−g(T)∗b+bg (T) - g (T) * a + a > g (T) - g (T) * b + bg(T)−g(T)∗a+a>g(T)−g(T)∗b+b
即证 (1−g(T))∗a>(1−g(T))∗b(1 - g (T)) * a > (1 - g (T)) * b(1−g(T))∗a>(1−g(T))∗b
又∵1>g(T)>0,a>b又\because 1 > g (T) > 0, a > b又∵1>g(T)>0,a>b
得证。
#include <map>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
template <typename T> T Max (T x, T y) { return x > y ? x : y; }
template <typename T> T Min (T x, T y) { return x < y ? x : y; }
template <typename T> T Abs (T x) { return x > 0 ? x : -x; }
template <typename T>
void read (T &x) {
x = 0; T f = 1;
char ch = getchar ();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar ();
}
while (ch >= '0' && ch <= '9') {
x = (x << 3) + (x << 1) + ch - '0';
ch = getchar ();
}
x *= f;
}
template <typename T>
void write (T x) {
if (x < 0) {
x = -x;
putchar ('-');
}
if (x < 10) {
putchar (x + '0');
return;
}
write (x / 10);
putchar (x % 10 + '0');
}
template <typename T>
void print (T x, char ch) {
write (x); putchar (ch);
}
const int Maxn = 100;
const double eps = 1e-10;
int n;
double a[Maxn + 5];
int main () {
// freopen (".in", "r", stdin);
// freopen (".out", "w", stdout);
cin >> n; for (int i = 1; i <= n; i++) cin >> a[i];
sort (a + 1, a + 1 + n);
if (Abs (a[n] - 1) < eps) {
printf ("%.12lf", 1.0);
return 0;
}
double t = 1, tot = 0;
for (int i = n; i >= 1; i--) {
if (t * (1 - a[i]) * (tot + a[i] / (1 - a[i])) < t * tot)
break;
t *= (1 - a[i]);
tot += a[i] / (1 - a[i]);
}
printf ("%.12lf", t * tot);
return 0;
}