1. 程式人生 > 其它 >[USACO19FEB]Cow Dating P 題解

[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;
}