分析
作为一名OIer,当看到最大值最小时
一定可以想到二分答案
所以可以顺着这个思路往下
由于最后需要的结果是单调不下降的
所以我们可以考虑贪心
设当前二分答案为Temp
- 若当前在,若 那么可以直接
break
掉,因为无解return false
- 若当前那么
A[i]=min(A[i-1],A[i]+Temp)
else
可得A[i]=max(A[i]-Temp,A[i-1])
进而就OKay了。。。
代码
//P4105 #include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <cstring> #define LL long long #define Lowbit(X) (X&(-X)) #define Lson (X<<1) #define Rson (X<<1|1) #define Cl(X,Y) memset((X),(Y),sizeof(X)) #define FOR(i,A,B) for(LL i=A;i<=B;i++) #define BOR(i,A,B) for(LL i=A;i>=B;i--) #define FOR_SIDE(i,A) for(LL i=Head[A];i;i=Next[i]) #define INF 0x7fffffff using namespace std; const LL MAXN=5e6+10; LL Total,A,B,C,D,Num[MAXN],MOD,F[MAXN]; LL Ans,Cop[MAXN]; inline void File() { freopen(".in","r",stdin); freopen(".out","w",stdout); } inline LL Function(LL New) { return (New*New%MOD*New%MOD*A%MOD+New*New%MOD*B%MOD+New*C%MOD+D)%MOD; } inline bool Check(LL Temp) { bool Vis=true; FOR(i,1,Total) { if(Cop[i]+Temp<Cop[i-1]) { Vis=false; break; } if(Cop[i]<=Cop[i-1]) Cop[i]=min(Cop[i-1],Cop[i]+Temp); else Cop[i]=max(Cop[i]-Temp,Cop[i-1]); } return Vis; } int main() { //File(); scanf("%lld",&Total); scanf("%lld %lld %lld %lld",&A,&B,&C,&D); scanf("%lld %lld",&Num[1],&MOD); F[0]=Function(Num[0]); F[1]=Function(Num[1]); FOR(i,2,Total) { Num[i]=(F[i-1]+F[i-2])%MOD; F[i]=Function(Num[i]); } LL L=0,R=MOD; while(L<=R) { FOR(i,1,Total) Cop[i]=Num[i]; Cop[0]=-INF; LL Mid=(L+R)>>1; if(Check(Mid)) R=Mid-1,Ans=Mid; else L=Mid+1; } printf("%lld\n",Ans); //fclose(stdin); fclose(stdout); // system("pause"); return 0; }