您的位置:首页 > 其它

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

2017-10-31 11:38 267 查看

题目:

我是超链接

题解:

无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
,tz
,fs
,f
,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
%p);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: