[ABC276G] Count Sequences 题解

考虑差分,设 \(d_i=a_i-a_{i-1}\),特别的,\(d_1=a_1\),那么约束就变成了

  1. \(\displaystyle\sum d_i\le m\)
  2. 对所有 \(i>1\)\(d_i\not\equiv 0\pmod 3\)

发现 \(d_1\) 非常特殊,于是可以单独考虑 \(d_1\equiv 0\pmod 3\)。以下设 \(d_1\not\equiv 0\pmod 3\)\(d_1\equiv 0\pmod 3\) 同理。

那么 \(d_i\) 只能是 \(3k+1\)\(3k+2\) 的形式。考虑枚举形如 \(3k+2\)\(d_i\) 的数量,设其为 \(c\),那么 \(3k+1\) 形式的数的数量即为 \(n-c\),方案数为 \(\displaystyle{n\choose c}\)。于是剩下的步骤相当于将不超过 \(\lfloor\dfrac{m-2c-(n-c)}{3}\rfloor\) 组物品放置在 \(n\) 个箱子内,这玩意可以插板+前缀和预处理。

#include <atcoder/all>
#include <iostream>

using namespace std;
using LL = atcoder::modint998244353;

const int kM = 4e6 + 1, kV = 1.4e7 + 1;

int n, m;
LL f[kV], ivf[kV], ans, s[kM];

LL C(int n, int m) { return f[n] * ivf[m] * ivf[n - m]; }

int main() {
  ios_base::sync_with_stdio(0), cin.tie(0);
  cin >> n >> m;
  int v = n + m / 3;
  f[0] = 1;
  for (int i = 1; i <= v; ++i) {
    f[i] = f[i - 1] * i;
  }
  ivf[v] = f[v].inv();
  for (int i = v; i >= 1; --i) {
    ivf[i - 1] = ivf[i] * i;
  }
  s[0] = 1;
  for (int i = 1; i <= m / 3; ++i) {
    s[i] = s[i - 1] + C(i + n - 1, n - 1);
  }
  for (int c = 0, _m = m - n; _m >= 0 && c <= n; ++c, --_m) {
    ans += C(n, c) * s[_m / 3];
  }
  for (int c = 0, _m = m - (n - 1); _m >= 0 && c < n; ++c, --_m) {
    ans += C(n - 1, c) * s[_m / 3];
  }
  cout << ans.val();
  return 0;
}
posted @ 2023-03-24 18:53  bykem  阅读(75)  评论(1)    收藏  举报