「Andrey and Problem」题解

做法超级简单,先从小到大排序,然后从后向前扫,选上更优就选上,不然就 \(break\)


证明。

反证法:假设选择集合不是后缀

假设现在有一个选择集合 \(S\)(存储的是下标),找到这个集合出现的空隙(即 \(i \notin S,i-1\in S\))。

令 $$T = \complement_S{i - 1}$$

令 $$f(P) = \Pi(1 - x_{p_i}), g(P) = \sum \frac{x_{p_i}}{1 - x_{p_i}},a = x_i, b = x_{i - 1}$$

则有:\(a > b\)

容易得到计算答案的式子: $$f (P) * g (P)$$

即证 $$f(T \bigcup {i}) * g(T \bigcup {i}) > f(T \bigcup {i - 1}) * g(T \bigcup {i - 1})$$

即证 $$f(T) * (1 - a) * (g (T) + \frac{a}{1-a}) > f(T) * (1 - b) * (g (T) + \frac{b}{1-b})$$

即证 $$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) + a * f (T) > f(T) * g (T) * (1 - b) + b * f (T)$$

即证 $$g (T) - g (T) * a + a > g (T) - g (T) * b + b$$

即证 $$(1 - g (T)) * a > (1 - g (T)) * b$$

\[又\because 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;
}
posted @ 2021-09-24 13:42  C2022lihan  阅读(40)  评论(1编辑  收藏  举报