[HEOI2014]南园满地堆轻絮
Description
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;
}
只要有想见的人,就不是孤身一人了。