「联合省选 2020 A」组合数问题

本文最后更新于:March 24, 2022 pm

之前以为是我不会的科技题,没想到是勾巴题((

观察到多项式次数 $m\le 1e3$,考虑计算每项的贡献:

$$\sum\limits_{i=0}^m a_i\sum\limits_{k=0}^n k^i x^k \dbinom n k$$

将 $k^i$ 用第二类斯特林数换掉:

$$\sum\limits_{i=0}^m a_i\sum\limits_{k=0}^nx^k\dbinom n k\sum\limits_{j=0}^{\min(k,i)}\dbinom k j\begin{Bmatrix}i\\j\end{Bmatrix}j!$$

然后推一下柿子:

$$\begin{aligned}\sum\limits_{i=0}^m a_i\sum\limits_{k=0}^nx^k\dbinom n k\sum\limits_{j=0}^{\min(k,i)}\dbinom k j\begin{Bmatrix}i\\j\end{Bmatrix}j!&=\sum\limits_{i=0}^m\sum\limits_{j=0}^ia_i\begin{Bmatrix}i\\j\end{Bmatrix}j!\sum\limits_{k=j}^nx^k\dbinom n k\dbinom k j\\ &=\sum\limits_{i=0}^m\sum\limits_{j=0}^ia_i\begin{Bmatrix}i\\j\end{Bmatrix}j!\sum\limits_{k=j}^nx^k\dbinom{n}{j}\dbinom{n-j}{k-j}\\ &=\sum\limits_{i=0}^m\sum\limits_{j=0}^ia_i\begin{Bmatrix}i\\j\end{Bmatrix}j!\dbinom n j x^j\sum\limits_{k=0}^{n-j}\dbinom{n-j}{k}x^k\\ &=\sum\limits_{i=0}^m\sum\limits_{j=0}^ia_i\begin{Bmatrix}i\\j\end{Bmatrix}j!\dbinom n j x^j(x+1)^{n-j}\end{aligned}$$

然后直接算就完了,时间复杂度 $\mathrm{O(m^2)}$。

$\texttt{Code:}$

#include <bits/stdc++.h>
using namespace std;
int cmd;
inline int add(int a, int b) {a += b; return a < cmd ? a : a - cmd;}
inline int sub(int a, int b) {a -= b; return a < 0 ? a + cmd : a;}
inline int mul(int a, int b) {return 1ll * a * b % cmd;}
int fpow(int a, int b) {
	int res = 1;
	for (; b; b >>= 1, a = mul(a, a))
		if (b & 1) res = mul(res, a);
	return res;
}
const int maxn = 1e3 + 5;
int n, x, m, ans, S2[maxn][maxn], pw[maxn];
int main() {
	scanf("%d%d%d%d", &n, &x, &cmd, &m);
	S2[0][0] = S2[1][1] = 1;
	for (int i = 2; i <= m; i++)
	for (int j = 1; j <= i; j++) S2[i][j] = add(S2[i - 1][j - 1], mul(S2[i - 1][j], j));
	for (int i = 0; i <= m; i++) pw[i] = fpow(x + 1, n - i);
	for (int i = 0; i <= m; i++) {
		int a; scanf("%d", &a);
		int p = 1;
		for (int j = 0; j <= min(i, n); p = mul(p, mul(x, n - j)), j++)
			ans = add(ans, mul(a, mul(S2[i][j], mul(p, pw[j]))));
	}
	printf("%d", ans);
	return 0;
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!