P1982 [NOIP2013 普及组] 小朋友的数字 题解

小邱

2022-03-26 09:46:16

Personal

题目链接:[P1982 [NOIP2013 普及组] 小朋友的数字](https://www.luogu.com.cn/problem/P1982) 这道题分为两个小问,第一问是求最大连续子序列和 有了特征值,求分数就很简单了! ```cpp #include<bits/stdc++.h> typedef unsigned long long ull; typedef long long ll; using namespace std; const int N=1000005; ll a[N],b[N]; int main() { int n,i; ll x,ans,k=-1e9,l=-1e9,mod; scanf("%d%lld",&n,&mod); for(i=1;i<=n;i++) { scanf("%lld",&x); if(l>0) { l+=x; } else { l=x; } k=max(k,l); a[i]=k%mod; } k=-1e9; b[1]=a[1]; ans=a[1]; for(i=2;i<=n;i++) { k=max(k,a[i-1]+b[i-1]); b[i]=k; if(ans<k) { ans=k%mod; } } printf("%lld",ans); return 0; } ``` 这个时候我们发现b数组本质上其实只关系到b[i-1],所以我们不妨定义变量,节省空间: ```cpp #include<bits/stdc++.h> typedef unsigned long long ull; typedef long long ll; using namespace std; const int N=1000005; ll a[N]; int main() { int n,i; ll x,ans=-1e9,k=-1e9,l=-1e9,mod; scanf("%d%lld",&n,&mod); for(i=1;i<=n;i++) { scanf("%lld",&x); if(l>0) { l+=x; } else { l=x; } k=max(k,l); a[i]=k%mod; } k=-1e9; l=a[1]; ans=a[1]; for(i=2;i<=n;i++) { k=max(k,a[i-1]+l); l=k; if(ans<k) { ans=k%mod; } } printf("%lld",ans); return 0; } ``` 我们再次观察,第一个for循环是求出a[i],而后面关系到a[i-1],我们不妨将这两个for循环综合起来: ```cpp #include<bits/stdc++.h> typedef unsigned long long ull; typedef long long ll; using namespace std; const int N=1000005; int main() { int n,i; ll x,ans,k=-1e9,l,mod,p,q; scanf("%d%lld%lld",&n,&mod,&x); ans=x; l=x; k=x; p=x; q=-1e9; for(i=2;i<=n;i++) { scanf("%lld",&x); if(l>0) { l+=x; } else { l=x; } q=max(q,k%mod+p); p=q; k=max(k,l); a[i]=k%mod; if(ans<q) { ans=q%mod; } } printf("%lld",ans); return 0; } ``` 变量有点多,建议大家对照前后几个程序一起看,这样清晰一点