二分答案,验证方式为将当前的音符值降到尽量小,以便后来的付出小的代价就可以维持递增。
比较坑的是取余运算,在这里面取余运算一定要加括号,因为取余运算和乘除运算同级。不加括号将不符合取余运算的规则。
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int maxn = 5000000+10;
ll a[maxn];
ll b[maxn];
ll n, sa, sb, sc, sd, A, p;
ll calc(ll x) {
ll a = ((((sa%p)*((x*x)%p))%p)*(x%p))%p;
ll b = (((sb*x)%p)*(x%p))%p;
ll c = (sc*x)%p;
ll d = sd;
return ((((a%p+b%p)%p+c%p)%p+(d%p))%p)%p;
}
bool yanz(ll mid) {
memcpy(b, a, sizeof(a));
b[1] -= mid;
for (int i=2;i<=n;i++) {
if (b[i]<b[i-1]) {
b[i] += mid;
}
if (b[i]<b[i-1]) return false;
b[i] = max(b[i]-mid,b[i-1]);
}
return true;
}
int main() {
scanf("%lld %lld %lld %lld %lld %lld %lld", &n, &sa, &sb, &sc, &sd, &A, &p);
a[0] = 0, a[1] = A;
//按题目要求构造
for (int i=2;i<=n;i++) {
a[i] = (calc(a[i-1])+calc(a[i-2]))%p;
// cout<<a[i]<<endl;
}
//开始二分
ll l = 0, r = 2e9;
while (l<r) {
// cout<<l<<" "<<r<<endl;
ll mid = (l+r)/2;
if (yanz(mid)) r = mid;
else l = mid+1;
}
cout<<l;
return 0;
}

京公网安备 11010502036488号