[HEOI2014]南园满地堆轻絮

Description

[HEOI2014]南园满地堆轻絮

Solution

维护最大值的最小值,试试二分\(+\)贪心的套路,发现可以
二分\(x\),初始\(k=-INF\),使后一个数在比前一个数大的情况下尽量小,成为新的\(k\),如果后一个数\(+x\)仍然大于\(k\),则\(return\) \(false\)

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
#define mid ((l + r) >> 1)
#define INF 0x7fffffff
#define MAXN 5000010
ll n, Sa, Sb, Sc, Sd, MOD, l, r, ans, h;
ll a[MAXN];
inline ll read() {
	ll s = 0, w = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
	for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
	return s * w;
}
inline ll f(ll x) {
	return (((Sa * x % MOD * x % MOD * x % MOD + Sb * x  % MOD * x % MOD) + Sc * x) % MOD + Sd) % MOD;
}
inline bool check(ll x) {
	h = -INF;
	for (register ll i = 1; i <= n; i++) {
		if (h > a[i] + x) return false;
		h = max(h, a[i] - x);
	}
	return true;
}
int main() {
	n = read(), Sa = read(), Sb = read(), Sc = read(), Sd = read(), a[1] = read(), MOD = read();
	for (register ll i = 2; i <= n; i++)
		a[i] = (f(a[i - 1]) + f(a[i - 2])) % MOD;
	l = 0, r = MOD;
	while (l <= r) {
		if (check(mid)) ans = mid, r = mid - 1;
		else l = mid + 1;
	}
	printf("%lld", ans);
	return 0;
}
posted @ 2019-10-05 12:17  Agakiss  阅读(110)  评论(0编辑  收藏  举报