题目链接:ARC 102C

Takahashi 有 $n$ 个骰子,每个骰子有 $k$ 个面分别标号为 $1$ 到 $k$。对于每个 $i = 2, 3, \dots, 2k$,求满足以下条件的方案数对 $998244353$ 的值。

  • 投掷这 $n$ 个骰子,没有任何两个不同骰子的数字之和为 $i$。

注意骰子之间是相同的。也就是说,当存在整数 $k$ 使得两个方案数数字 $k$ 的骰子数量不同,那么这两个方案被认为是不同的。

数据范围:$2 \le n \le 2000$,$1 \le k \le 2000$。


Solution

由于数据范围只有 $2000$,我们考虑容斥

对于确定的 $i = 2, 3, \cdots, 2k$,我们枚举有至少 $j$ 对不满足条件的骰子。假如构成 $x$ 的无序数字对数量为 $tot$,那么这 $k$ 对骰子有 $\binom{tot}{j}$ 种方案数。

接下来考虑剩下的 $n - 2j$ 个骰子。问题转化为:有 $k$ 种数字,第 $i$ 种数字有 $a_i$ 个,这 $k$ 种数字一共有 $n - 2j$ 个。这个问题是平凡的,利用隔板法可以得到方案数 $\binom{n - 2j + k - 1}{k - 1}$。

故我们利用容斥得到答案:

$$ \sum_{j = 0} ^ {\min(tot, \left\lfloor\frac{n}{2}\right\rfloor)} (-1) ^ j\binom{tot}{j}\binom{n - 2j + k - 1}{k - 1} $$

时间复杂度:$\mathcal O(nk)$。


Code

#include <cstdio>
#include <algorithm>

const int N = 4e3 + 5;
const int P = 998244353;

int n, k, c[N][N];

void init(int n) {
    c[0][0] = 1;
    for (int i = 1; i <= n; i++) {
        c[i][0] = 1;
        for (int j = 1; j <= i; j++) {
            c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % P;
        }
    }
}
void add(int &x, int y) {
    (x += y) >= P && (x -= P);
}
int main() {
    scanf("%d%d", &k, &n);
    init(n + k);
    for (int i = 2; i <= k + k; i++) {
        int cnt = 0, ans = 0;
        for (int j = 1; i - j >= j; j++) {
            cnt += (j <= k && i - j <= k);
        }
        for (int j = 0, sgn = 1; j <= cnt && j + j <= n; j++, sgn = P - sgn) {
            add(ans, 1LL * sgn * c[cnt][j] % P * c[n - 2 * j + k - 1][k - 1] % P);
        }
        printf("%d\n", ans);
    }
    return 0;
}
最后修改:2019 年 06 月 28 日
如果觉得我的文章对你有用,请随意赞赏