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;
}
posted @   风浔凌  阅读(104)  评论(0编辑  收藏  举报
编辑推荐:
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
阅读排行:
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!
点击右上角即可分享
微信分享提示