[noip2013]小朋友的数字(dp+规律)

题目:

我是超链接

题解:

无dp暴力:60pts
不行啊这个n^2,我还是用dp吧,f[i]表示前i个手上的数(必选i)的最大值:80pts
Emmm看来是爆longlong了。。确实有一个比longlong更大的,但是我们还是用科学的方法吧
很容易发现特征值是不降的,那么也可以发现分数是不降的
如果上一位的特征值小于0,那上一位肯定带不来什么好贡献,并且也可以知道前面的特征值全都是小于0的常数列(除第一位),那这一位小朋友的分数就是第二位小朋友的分数
如果上一位的特征值大于0,那肯定会增加贡献,就直接是上一位小朋友的特征值+分数
最后还需要比较一下最大的小朋友和第一位小朋友的值,正因为要找到最大的小朋友,我们不能在更新值的时候直接取模,还要先确认比第一位小朋友大

代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#define LL long long
#define N 1000005
using namespace std;
const LL INF=1e18;
LL ss[N],tz[N],fs[N],f[N],p;
int main()
{
    int n,i,j;
    scanf("%d%lld",&n,&p);
    for (i=1;i<=n;i++) scanf("%lld",&ss[i]);
    tz[1]=f[1]=ss[1];
    for (i=2;i<=n;i++) 
    {
        f[i]=ss[i]+max(0ll,f[i-1]);
        tz[i]=max(tz[i-1],f[i]);
    }
    bool vv=0;
    fs[1]=ss[1];fs[2]=ss[1]*2;
    if (fs[1]<=fs[2]) vv=1;
    for (i=3;i<=n;i++)
      if (tz[i-1]>0) 
      {
        fs[i]=tz[i-1]+fs[i-1];
        if (fs[i]>=fs[1]) vv=1;
        if (fs[i]>INF) fs[i]%=p;
      }
      else fs[i]=fs[2];

    if (!vv) printf("%lld",fs[1]%p);
    else printf("%lld",fs[n]%p); 
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值