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

Alex_Wei
**搬运于
2025-08-24 22:26:56,当前版本为作者最后更新于2020-12-20 12:18:36,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
题意简述:给定 ,求有多少种序列 满足 且对于所有 有 。
首先,看到 考虑能否 DP。
考虑第 堆零食时,第 堆零食的高度会影响方案的可行性(即有后效性),所以不能单纯设 表示 的合法方案数。
不难想到按照 第 堆零食是否靠到了第 堆零食上(即 与 的关系) 将 时的合法方案数分成两类情况讨论:设 表示 且 (即第 堆零食靠到了第 堆零食上,此时不关心 的大小)的合法方案数, 表示 且 的合法方案数。
接下来推转移方程:记 。
:此时应满足 ,但因为 的定义,不需要满足 ,所以此时 的限制为 ,即
。:此时应满足 且 ,即 ,即
。综上, 的转移方程为:
$$f_{i,j}=\sum_{k=l}^m f_{i-1,k}+\sum_{k=l}^r g_{i-1,k} $$。根据上面的思路,不难推出 的转移方程:
。补充说明:当 时, 应同时满足 且 ,又因为 的非负性有 ,所以此时 。
由于最后一堆零食没有高度限制,所以最终答案为 。
最后前缀和优化 + 滚动数组优化即可,时间复杂度 。参考代码:
const int N=7e3+5; ll n,m,d[N],f[2][N],g[2][N]; int main(){ cin>>n>>m; for(int i=1;i<=n;i++)cin>>d[i]; for(int i=0;i<=m;i++)f[1][i]=i+1; for(int i=2;i<=n;i++){ int p=i&1,q=p^1; for(int j=0;j<=m;j++){ int l=max(0ll,j-d[i]),r=min(m,j+d[i-1]); f[p][j]=(f[q][m]+g[q][r]-(l?f[q][l-1]+g[q][l-1]:0)+(j?f[p][j-1]:0)+mod)%mod; g[p][j]=((l?f[q][l-1]+g[q][l-1]:0)+(j?g[p][j-1]:0))%mod; } } cout<<(f[n&1][m]+g[n&1][m])%mod<<endl; return 0; }
- 1
信息
- ID
- 5831
- 时间
- 1000ms
- 内存
- 250MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者