CF1716F Bags with Balls

题意

\(n\) 个盒子,每个盒子里有编号为 \(1 \to m\)\(m\) 个球。

从每个盒子拿一个球,设取出的编号是奇数的球的数量为 \(F\).

求所有取球方案的 \(F ^ k\) 之和。

Sol

不难想到答案为:

\[\sum_{i = 0} ^ n \binom{n}{i} i ^ k (\lceil \frac{m}{2}\rceil) ^ i (\lfloor \frac{m}{2} \lfloor) ^ {n - i} \]

套路地,将 \(i ^ k\) 转为下降幂。

\[\sum_{i = 0} ^ n \sum_{j = 0} ^ k \begin{Bmatrix} k \\ j\end{Bmatrix} i ^ {\underline j} \binom{n}{i} (\lceil \frac{m}{2} \rceil) ^ i (\lfloor \frac{m}{2} \lfloor) ^ {n - i} \]

合并组合数和下降幂,调整求和顺序。

\[\sum_{j = 0} ^ k \begin{Bmatrix} k \\ j\end{Bmatrix} \sum_{i = 0} ^ n n ^ {\underline j} \binom{n - j}{i - j} (\lceil \frac{m}{2} \rceil) ^ i (\lfloor \frac{m}{2} \lfloor) ^ {n - i} \]

后面这一坨很像二项式定理啊。

发现直接提个 \((\lceil \frac{m}{2} \rceil) ^ j\) 就能直接合并了。

\[\sum_{j = 0} ^ k \begin{Bmatrix} k \\ j \end{Bmatrix} (\lceil \frac{m}{2} \rceil) ^ j m ^ {n - j} \]

直接计算即可。

Code

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <array>
#define int long long
using namespace std;
#ifdef ONLINE_JUDGE

#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
char buf[1 << 23], *p1 = buf, *p2 = buf, ubuf[1 << 23], *u = ubuf;

#endif
int read() {
	int p = 0, flg = 1;
	char c = getchar();
	while (c < '0' || c > '9') {
		if (c == '-') flg = -1;
		c = getchar();
	}
	while (c >= '0' && c <= '9') {
		p = p * 10 + c - '0';
		c = getchar();
	}
	return p * flg;
}
void write(int x) {
	if (x < 0) {
		x = -x;
		putchar('-');
	}
	if (x > 9) {
		write(x / 10);
	}
	putchar(x % 10 + '0');
}
const int N = 2e3 + 5, mod = 998244353;

int pow_(int x, int k, int p = mod) {
	int ans = 1;
	while (k) {
		if (k & 1) ans = ans * x % p;
		x = x * x % p;
		k >>= 1;
	}
	return ans;
}

array <array <int, N>, N> f;

void Mod(int &x) {
	if (x >= mod) x -= mod;
	if (x < 0) x += mod;
}

signed main() {
	f[0][0] = 1;
	for (int i = 1; i <= 2000; i++)
		for (int j = 1; j <= 2000; j++)
			f[i][j] = f[i - 1][j - 1] + j * f[i - 1][j] % mod, Mod(f[i][j]);
	int T = read();
	while (T--) {
		int n = read(), m = read(), k = read();
		int ans = 0, tp = 1;
		for (int j = 0; j <= min(k, n); j++) {
			ans += tp * f[k][j] % mod * pow_((m + 1) / 2, j) % mod * pow_(m, n - j) % mod, Mod(ans);
			tp = tp * (n - j) % mod;
		}
		write(ans), puts("");
	}

	return 0;
}
posted @ 2024-02-25 17:22  cxqghzj  阅读(8)  评论(0编辑  收藏  举报