Yet Another Subarray Problem - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
这道题是一道dp状态跟模数有关的dp,难点就是想到以模数作为dp状态之一,因为 m 很小 (这个以模数作为dp状态是真的妙!!!)
设dp[i][j]为以 i 结尾,取了若干个连续 x个数字( i 一定取走 ),j=x%m
为了跟方便的写题以及不容易出错
1.当 x 为j的倍数时且不为 0,规定 j=m(这要主要是好写 关于 k 的向上取整)
2.由于以 i 结尾至少取走一个数,所以 j>0
dp转移:dp[i-1][j]已知推广出新的状态:
if(j==m) dp[i][1]=max(dp[i][1],dp[i-1][j]+a[i]-k); //在j==1时,新出现了一个区间,由于向上取整,故要及时 -k
else dp[i][j+1]=max(dp[i][j+1],dp[i-1][j]+a[i]);
初始化: for(int i=1;i<=n;i++) dp[i][1]=a[i]-k;
ans=max(dp[i][j])
#include<bits/stdc++.h> using namespace std; #define ll long long #define db long double #define mp make_pair #define pb push_back #define popb pop_back #define fi first #define se second #define popcount __builtin_popcount #define popcountll __builtin_popcountll const int N=3e5+10; //const int M=; //const int inf=(int)1e9; const ll INF=(ll)1e18; int T,n,m,k,a[N]; ll dp[N][11]; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } int main() { // freopen("","r",stdin); // freopen("","w",stdout); // ios::sync_with_stdio(0); // cin.tie(0); n=read(),m=read(),k=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=0;i<=n;i++) for(int j=0;j<=m;j++) dp[i][j]=-INF; for(int i=1;i<=n;i++) dp[i][1]=a[i]-k; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { if(dp[i-1][j]==-INF) continue; if(j==m) dp[i][1]=max(dp[i][1],dp[i-1][j]+a[i]-k); else dp[i][j+1]=max(dp[i][j+1],dp[i-1][j]+a[i]); } ll ans=0; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) ans=max(ans,dp[i][j]); printf("%lld\n",ans); return 0; }
标签:ch,const,int,ll,CF1197D,dp,define From: https://www.cnblogs.com/Willette/p/17552235.html