题解 P6620【[省选联考 2020 A 卷] 组合数问题】
前置知识:https://www.cnblogs.com/caijianhong/p/18409103
题目描述
众所周知,小葱同学擅长计算,尤其擅长计算组合数。小葱现在希望你计算
\[\left(\sum_{k=0}^{n}f(k)\times x^k\times \binom{n}{k}\right)\bmod p
\]
的值。其中 \(n\), \(x\), \(p\) 为给定的整数,\(f(k)\) 为给定的一个 \(m\) 次多项式 \(f(k) = a_0 + a_1k + a_2k^2 + \cdots + a_mk^m\)。\(\binom{n}{k}\) 为组合数,其值为 \(\binom{n}{k} = \frac{n!}{k!(n-k)!}\)。
对于所有测试数据:\(1\le n, x, p \le 10^9, 0\le a_i\le 10^9, 0\le m \le \min(n,1000)\)。
solution
\(f(k)\) 转为下降幂形式 \(\sum_{i=0}^m b_ik^{\underline i}\)。则有
\[\begin{aligned}
&=\sum_{k=0}^n\sum_{i=0}^mb_ik^{\underline i}x^k\binom n k\\
&=\sum_{k=0}^n\sum_{i=0}^mb_in^{\underline i}x^k\binom {n-i} {k-i}\\
&=\sum_{i=0}^mb_in^{\underline i}\sum_{k=0}^nx^k\binom {n-i} {k-i}\\
&=\sum_{i=0}^mb_in^{\underline i}x^i\sum_{k=0}^{n-i}x^k\binom {n-i} {k}\\
&=\sum_{i=0}^mb_in^{\underline i}x^i(1+x)^{n-i}
\end{aligned}
\]
足以计算。依实现,可以 \(O(m^2\log n)\) 或 \(O(m^2)\)。
code
#include <bits/stdc++.h>
using namespace std;
#ifdef LOCAL
#define debug(...) fprintf(stderr, ##__VA_ARGS__)
#else
#define endl "\n"
#define debug(...) void(0)
#endif
using LL = long long;
template <class T>
using must_int = enable_if_t<is_integral<T>::value, int>;
template <int id>
struct modint {/*{{{*/
static int mod;
static unsigned umod;
static void setmod(int p) { mod = umod = p; }
unsigned v;
modint() : v(0) {}
template <class T, must_int<T> = 0>
modint(T x) {
x %= mod;
v = x < 0 ? x + mod : x;
}
modint operator+() const { return *this; }
modint operator-() const { return modint() - *this; }
friend int raw(const modint &self) { return self.v; }
friend ostream& operator<<(ostream& os, const modint &self) {
return os << raw(self);
}
modint &operator+=(const modint &rhs) {
v += rhs.v;
if (v >= umod) v -= umod;
return *this;
}
modint &operator-=(const modint &rhs) {
v -= rhs.v;
if (v >= umod) v += umod;
return *this;
}
modint &operator*=(const modint &rhs) {
v = 1ull * v * rhs.v % umod;
return *this;
}
modint &operator/=(const modint &rhs) {
assert(rhs.v);
return *this *= qpow(rhs, mod - 2);
}
template <class T, must_int<T> = 0>
friend modint qpow(modint a, T b) {
modint r = 1;
for (; b; b >>= 1, a *= a)
if (b & 1) r *= a;
return r;
}
friend modint operator+(modint lhs, const modint &rhs) { return lhs += rhs; }
friend modint operator-(modint lhs, const modint &rhs) { return lhs -= rhs; }
friend modint operator*(modint lhs, const modint &rhs) { return lhs *= rhs; }
friend modint operator/(modint lhs, const modint &rhs) { return lhs /= rhs; }
bool operator==(const modint &rhs) const { return v == rhs.v; }
bool operator!=(const modint &rhs) const { return v != rhs.v; }
};/*}}}*/
template <int id>
unsigned modint<id>::umod;
template <int id>
int modint<id>::mod;
using mint = modint<-1>;
int n, m;
mint X, b[1010], S[1010][1010];
int main() {
#ifndef LOCAL
cin.tie(nullptr)->sync_with_stdio(false);
#endif
cin >> n >> X.v >> mint::mod >> m;
mint::setmod(mint::mod);
X.v %= mint::mod;
S[0][0] = 1;
for (int i = 1; i <= m; i++) {
S[i][0] = 0;
for (int j = 1; j <= i; j++) S[i][j] = S[i - 1][j - 1] + S[i - 1][j] * j;
}
for (int i = 0; i <= m; i++) {
int x;
cin >> x;
for (int j = 0; j <= i; j++) b[j] += S[i][j] * x;
}
mint ans = 0;
mint now = 1;
for (int i = 0; i <= m; i++) {
ans += b[i] * now * qpow(X, i) * qpow(1 + X, n - i);
now *= n - i;
}
cout << ans << endl;
return 0;
}
本文来自博客园,作者:caijianhong,转载请注明原文链接:https://www.cnblogs.com/caijianhong/p/18353926/solution-P6620