Atcoder dp_m Candies 前缀和优化dp

26 篇文章 0 订阅

文章目录

题意

n n n个孩子发 k k k颗糖,每个孩子最多拿到 a i a_i ai颗,问有多少种分法.
n ≤ 100 , k ≤ 1 0 5 n\leq 100,k\leq 10^5 n100,k105.

题解

考虑 d p . dp. dp.
非常裸的 d p dp dp如下.

for (int i=1;i<=n;++i) {
  for (int j=k;~j;--j)
    for (int l=j+1;l<=j+a[i];++l) 
      dp[l]=(dp[l]+dp[j])%mod;
}

复杂度为 O ( n × k 2 ) O(n \times k^2) O(n×k2),显然不能通过.
d p j dp_j dpj为前 i i i(滚动数组)个孩子有 k k k颗糖没有发到的总分法数.
假设当前的孩子最多能够分到 k k k颗糖而不是 a i a_i ai颗,则
d p k = 上 一 个 d p k dp_k=上一个dp_k dpk=dpk(这个孩子没分到糖).
d p k − 1 = 上 一 个 d p k − 1 + d p k dp_{k-1}=上一个dp_{k-1}+dp_k dpk1=dpk1+dpk(这个孩子可以分到一颗糖,也可以不分到糖).
以此类推, d p 0 = 上 一 个 d p 0 + d p 1 + . . . + d p k − 1 + d p k dp_0=上一个dp_0+dp_1+...+dp_{k-1}+dp_k dp0=dp0+dp1+...+dpk1+dpk.
但是实际上这个孩子最多只能分到 a i a_i ai颗糖,因此我们要把超过 a i a_i ai的部分减掉.
由于刚才已经做过前缀和,对 j j j只需要减掉 d p j + a i + 1 dp_{j+a_i+1} dpj+ai+1这个位置的答案就可以了.
这样一来本题就解决了.
谢谢大家.

const int yuzu=2e5,mod=1e9+7;
typedef ll fuko[yuzu|10];
fuko dp;
int main() {
  int i,n,k,a;
  read(n),read(k);
  for (dp[k]=1;read(a);) {
    for (i=k;i--;) dp[i]+=dp[i+1];
    for (i=0;i<k;++i) dp[i]=(dp[i]-dp[i+a+1])%mod;
  }
  printf("%lld\n",*dp);
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值