Educational Codeforces Round 133 (Rated for Div. 2) - F. Bags with Balls

题意

给出 \(n\), \(m\), \(k\), 对 \(n\) 长度的数组, 每个元素可以选 \([1,m]\) 中的任意一个值, 一个数组的贡献为该数组中奇数的个数的 \(k\) 次方( \(k\leq 2000\) ), 求所有数组的贡献和模 \(998\ 244\ 353\)

思路

首先, 记 \(a = \lfloor\frac{m + 1}{2}\rfloor\), \(b = m - a\), 分别表示可以选择的奇数数目和偶数数目

那么总贡献即为

\[\begin{align} Ans &= \sum_{i=0}^n \binom{n}{i, n-i} \cdot a^i \cdot b^{n-i} \cdot i^k \end{align} \]

\(i^k\) 不好处理, 考虑对其进行 第二类斯特林数 展开, 并更换枚举顺序

\[i^k = \sum_{j=0}^\infin P(i,j)\cdot S(k,j) \]

则有

\[\begin{align} Ans &= \sum _{i=0}^n \binom{n}{i, n-i} \cdot a^i \cdot b^{n-i} \sum _{j=0}^\infin P(i,j) \cdot S(k,j) \\ &= \sum _{j=0}^\infin \sum _{i=0}^n \frac{n!}{i!\cdot (n-i)!} \cdot a^i \cdot b^{n-i} \cdot \frac{i!}{(i-j)!} \cdot S(k,j) \\ &= \sum _{j=0}^\infin \sum _{i=0}^n \frac{n!}{(n-i)!(i-j)!} \cdot a^i \cdot b^{n-i} \cdot S(k,j) \\ &= \sum _{j=0}^\infin \frac{n!}{(n-j)!} \cdot S(k,j) \cdot a^j \sum _{i=0}^n \frac{(n-j)!}{(n-i)!(i-j)!} \cdot a^{i - j} \cdot b^{n-i} \\ &\text{显然,}\ i < j \ \text{时, 第二个求和均为}\ 0 \\ &= \sum _{j=0}^\infin \frac{n!}{(n-j)!} \cdot S(k,j) \cdot a^j \sum _{i=j}^n \frac{(n-j)!}{(n-i)!(i-j)!} \cdot a^{i - j} \cdot b^{n-i} \\ &= \sum _{j=0}^\infin \frac{n!}{(n-j)!} \cdot S(k,j) \cdot a^j \sum _{i=0}^{n-j} \frac{(n-j)!}{(n-i-j)!i!} \cdot a^{i} \cdot b^{n-i-j} \\ &= \sum _{j=0}^\infin \frac{n!}{(n-j)!} \cdot S(k,j) \cdot a^j \cdot (a + b)^{n - j} \\ & \text{观察到}\ j > k \ \text{时}\ S(k,j)=0 \\ &= \sum _{j=0}^k \frac{n!}{(n-j)!} \cdot S(k,j) \cdot a^n \cdot m^{n-j} \end{align} \]

\(\frac{n!}{(n-j)!}\) 是个下降幂, 可以迭代 \(j\) 的时候求, \(a^j\), \(m^{n-j}\), 一个可以倒着枚举, 另一个可以跑预处理

代码

这里直接跑快速幂了, 懒得预处理

#include <bits/stdc++.h>
#define de(x) std::cout << #x << " = " << (x) << std::endl
using i64 = long long;
constexpr int MOD = 998244353;

int mul(int x,int y) {
    return (i64)x * y % MOD;
}
int add(int x,int y) {
    x += y;
    if(x >= MOD) x -= MOD;
    if(x < 0) x += MOD;
    return x;
}

int qpow(int b,int p) {
    int res = 1;
    for(;p;p>>=1,b=(i64)b*b%MOD) if(p&1) res = (i64)res * b % MOD;
    return res;
}

constexpr int K = 2006;
std::vector<std::vector<int>> ss(K, std::vector<int>(K));

int S(int n,int m) {
    if(n < m || m < 0) return 0;
    return ss[n][m];
}

void sol() {
    int n,m,k;
    std::cin >> n >> m >> k;
    int res = 0;
    int qwq = n;
    int a = (m + 1) / 2, b = m - a;
    for(int j=1;j<=k&&j<=n;++j) {
        res = add(res, mul(S(k, j), mul(qpow(a, j), mul(qpow(m, n - j), qwq))));
        qwq = mul(qwq, n - j);
    }
    std::cout << res << '\n';
}

int main(int argc, char const *argv[])
{
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(nullptr); std::cout.tie(nullptr);

    ss[1][1] = 1;
    for(int n=2;n<K;++n) {
        for(int m=1;m<n;++m) {
            ss[n][m] = add(mul(m, ss[n - 1][m]), ss[n - 1][m - 1]);
        }
        ss[n][n] = 1;
    }

    int t;
    std::cin >> t;
    while(t --> 0)
        sol();
    
    return 0;
}
posted @ 2022-08-10 11:21  LacLic  阅读(36)  评论(0编辑  收藏  举报