[省选联考 2020 A 卷] 组合数问题

题面

题解

\(F(n, m) = \sum_{k=0}^n k^mx^k\binom nk\),于是答案就是 \(\sum_i a_iF(n, i)\)

那么有:

\[\begin{aligned} F(n, m) &= \sum_{k=0}^n k^m x^k \binom nk\\ &= n\sum_{k=0}^n k^{m-1}x^k\binom {n-1}{k-1} \end{aligned} \]

然后:

\[\begin{aligned} F(n, m) &= \sum_{k=0}^n k^mx^k\binom nk\\ &= \sum_{k=0}^n k^mx^k\left(\binom {n-1}k + \binom{n-1}{k-1} \right)\\ &= F(n-1,m) + \frac 1n F(n, m + 1) \end{aligned} \]

也就是说:\(F(n, m) = n(F(n, m - 1) - F(n - 1, m - 1))\)

边界为 \(F(n, 0) = (x + 1)^n\)

代码

#include <bits/stdc++.h>

inline int read()
{
	int data = 0, w = 1; char ch = getchar();
	while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
	if (ch == '-') w = -1, ch = getchar();
	while (ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = getchar();
	return data * w;
}

const int N(1010);
int n, x, P, m, f[N], g[N], a[N];
int fastpow(int x, int y)
{
	int ans = 1;
	for (; y; y >>= 1, x = 1ll * x * x % P)
		if (y & 1) ans = 1ll * ans * x % P;
	return ans;
}

int main()
{
	n = read(), x = read(), P = read(), m = read();
	for (int i = 0; i <= m; i++) a[i] = read();
	f[0] = fastpow(x + 1, n - m);
	for (int i = m - 1; ~i; i--)
	{
		g[0] = 1ll * f[0] * (x + 1) % P;
		for (int j = 1; j <= m - i; j++)
			g[j] = 1ll * (g[j - 1] - f[j - 1] + P) % P * (n - i) % P;
		for (int j = 0; j <= m - i; j++) f[j] = g[j];
	}
	int ans = 0;
	for (int i = 0; i <= m; i++) ans = (ans + 1ll * f[i] * a[i]) % P;
	printf("%d\n", ans);
	return 0;
}
posted @ 2020-06-27 14:36  xgzc  阅读(547)  评论(0编辑  收藏  举报