1 条题解
-
0
自动搬运
来自洛谷,原作者为

JHPOTATO
那也请不要忘记 落泪的眼睛 曾动容的心情搬运于
2025-08-24 23:18:04,当前版本为作者最后更新于2025-06-14 20:05:10,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
存在一个显然的性质:对于任意一个区间 ,设用其中元素至多能参加 场婚礼,那么对于任意 ,都可以找到一种合法的方案。
所以我们可以统计每个区间能参加婚礼的最大次数,并借助这个判定一个区间能否完全利用。
转移是简易的,因为只关心最大次数,所以只需要枚举断点,判断剩下元素总和对 取模是否为 即可。
为了判定简便,可以事先预处理达到每个余数至少要举办几场婚礼。
其余细节可以见代码。
代码
#include<bits/stdc++.h> using namespace std; template <typename T> void in(T &x){ char c=getchar(), f=1; while ((c<'0' || c>'9') && c!='-') c=getchar(); if (c=='-') f=-1, c=getchar(); for (x=0; c>='0' && c<='9'; c=getchar()) x=x*10+c-'0'; x*=f; } const int N=505; int n,d,r,al,dp[N][N]; long long s[N],f[N][N]; unordered_map<int,int>p; int main(){ in(n);in(d);in(r); for(int i=1;i<=n;i++){ al+=r;if(al>=d)al-=d; if(p.count(al))break; p[al]=i; } for(int i=1;i<=n;i++){ in(s[i]); if(s[i]%d==r)dp[i][i]=1,f[i][i]=s[i]/d; s[i]+=s[i-1]; } for(int l=1;l<n;l++){ for(int i=n-l;i;i--){ int j=i+l,mx=0; for(int k=i;k<j;k++){ f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]); mx=max(mx,dp[i][k]+dp[k+1][j]); } long long xx=(s[j]-s[i-1])%d; if(p.count(xx)&&p[xx]==mx+1)mx++;//如果res=0似乎会使mx变大(用0张巻白吃?) //但res=0如果出现,就一定是最后一项,也就是所有可达余数都已经能被计算出来了,多统计无影响 dp[i][j]=mx; if(p.count(xx)&&mx>=p[xx])f[i][j]=max(f[i][j],(s[j]-s[i-1]-p[xx]*1ll*r)/d); } } cout<<f[1][n]; return 0; } /* dp[i][j]->区间[i,j]至多能参加几场婚礼 f[i][j]->区间[i,j]的答案 显然,只要需求可达且不超过dp[i][j],都能凑出来 */
- 1
信息
- ID
- 12516
- 时间
- 2000ms
- 内存
- 2048MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者