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