ABC159F Knapsack for All Segments

[ABC159F] Knapsack for All Segments

一道很简单的 \(DP\) , 但是, 记得取模!!!

对于合法的区间 \((l, r)\) , 它对答案的贡献是 \(l * (n - r + 1)\) , 这样我们就可以在转移的过程中计算答案了, 有点费用提前计算的味道.

设状态: \(f(i, j)\) 表示在前 \(i\) 个数中和为 \(j\) 的方案的左端点下标之和.

转移很简单, 只需要特殊处理从 \(f(i - 1, 0)\) 转移过来的情况, 然后先转移选第 \(i\) 个的情况, 统计答案, 再转移不选的就行了.

\(code:\)

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

inline int read() {
  int x = 0, f = 1;
  char ch = getchar();
  for (; !isdigit(ch); ch = getchar())
    if (ch == '-') f = -1;
  for (; isdigit(ch); ch = getchar())
    x = (x << 1) + (x << 3) + (ch ^ 48);
  return x * f;
}

const int N = 3e3 + 5, mod = 998244353;

int n, s, a[N];
ll f[N][N], ans;

int main() {
  n = read(), s = read();
  for (int i = 1; i <= n; i++)
    a[i] = read();
  for (int i = 1; i <= n; i++) {
      f[i][a[i]] = (f[i - 1][0] + i) % mod;
    for (int j = a[i] + 1; j <= s; j++)
      f[i][j] = f[i - 1][j - a[i]];
    ans = (ans + f[i][s] * (n - i + 1) % mod) % mod;
    for (int j = 0; j <= s; j++)
      f[i][j] = (f[i][j] + f[i - 1][j]) % mod;
  }
  printf("%lld", ans);
  return 0;
}
posted @ 2021-10-15 15:36  sshadows  阅读(32)  评论(0编辑  收藏  举报