[USACO19FEB]Cow Dating P 题解
link
此为 CF442B Andrey and Problem 的弱化版。
(此为选数只留下一个算最大/最小概率此类题型的板子。。)
考虑 dp,易写出转移式:\(dp[i]=\prod (1-a_j)_{j<i}\times a_i+dp[i-1]\times (1-a_i)\)。
考虑当前我们是否要转移,即 \(dp[i]>dp[i-1]\)。
\(\prod (1-a_j)_{j<i}\times a_i+dp[i-1]\times (1-a_i)>dp[i-1]\)
\(=>\prod (1-a_j)^{j<i}>dp[i-1]\)。
多么美妙!但考虑 \(dp[i-1]\) 还是变量,考虑将其代换。
根据其定义,我们可以知道:
\(dp[i-1]=\sum_{j=1}^{i-1} a_j /(1-a_j)\prod (1-a_k)\)
好的,两边约掉,得 \(\sum_{j=1}^{i-1} \frac {a_j} {1-a_j}<1\)。
固定左端点,肯定要右端点越远越好,二分即可。
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <iostream>
#define LL long long
using namespace std;
#define Debug(x) cerr << #x << ' ' << x
#define hh cerr << endl
const int MAXN = 1e6 + 5;
int n;
long double a[MAXN], pre[MAXN], tmp[MAXN], maxx;
int main() {
scanf("%d", &n); tmp[0] = 1;
for(int i = 1; i <= n; i ++) scanf("%Lf", &a[i]), a[i] /= 1000000;
for(int i = 1; i <= n; i ++) {
pre[i] = pre[i - 1] + a[i] / (1 - a[i]); tmp[i] = tmp[i - 1] * (1 - a[i]);
}
for(int i = 1; i <= n; i ++) {
int t = lower_bound(pre + i, pre + 1 + n, 1 + pre[i - 1]) - pre;
t = min(t, n); maxx = max(maxx, (pre[t] - pre[i - 1]) * tmp[t] / tmp[i - 1]);
}
printf("%d", (int)floor(maxx * 1e6));
return 0;
}