HEOI2014 南国满地堆轻絮

题目链接:戳我

就是二分一个数,之后记录一个前缀max,然后和当前数做差再/2即可。(因为我们要使得原来的序列变成不下降序列,所以当然是要控制一个上限,以达到后面较小数能以尽可能小的代价增加)

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define MAXN 5000010
using namespace std;
int n,sa,sb,sc,sd,mod;
int a[MAXN];
inline int f(int x)
{
    int cur_ans1=1ll*x*x%mod*x%mod*sa%mod;
    int cur_ans2=1ll*x*x%mod*sb%mod;
    int cur_ans3=1ll*x*sc%mod;
    return (1ll*cur_ans1+cur_ans2+cur_ans3+sd)%mod;
}
inline bool check(int x)
{
    int maxx=0,cur_ans=0;
    for(int i=1;i<=n;i++)
    {
        maxx=max(maxx,a[i]);
        cur_ans=max(cur_ans,(maxx-a[i]+1)/2);
    }
    // printf("x=%d cur_ans=%d\n",x,cur_ans);
    if(cur_ans<=x) return true;
    return false;
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("ce.in","r",stdin);
    #endif
    scanf("%d%d%d%d%d%d%d",&n,&sa,&sb,&sc,&sd,&a[1],&mod);
    for(int i=2;i<=n;i++) a[i]=(f(a[i-2])+f(a[i-1]))%mod;
    // for(int i=1;i<=n;i++) printf("a[%d]=%d\n",i,a[i]);
    int l=0,r=mod,ans;
    while(l<r)
    {
        int mid=(l+r)>>1;
        if(check(mid)) ans=mid,r=mid;
        else l=mid+1;
    }
    printf("%d\n",ans);
    return 0;
}
上一篇:洛谷P5282 【模板】快速阶乘算法(多项式多点求值+MTT)


下一篇:[JXOI2018]排序问题