二分答案,验证方式为将当前的音符值降到尽量小,以便后来的付出小的代价就可以维持递增。
比较坑的是取余运算,在这里面取余运算一定要加括号,因为取余运算和乘除运算同级。不加括号将不符合取余运算的规则。
#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;
}