[洛谷P4091][HEOI2016/TJOI2016]求和
题目大意:给你$n(n\leqslant10^5)$,求:
$$
\sum\limits_{i=0}^n\sum\limits_{j=0}^i\begin{Bmatrix}i\\j\end{Bmatrix}\times2^j\times j!
$$
$\begin{Bmatrix}n\\m\end{Bmatrix}$表示第二类斯特林数,递推公式为$\begin{Bmatrix}n\\m\end{Bmatrix}=m\begin{Bmatrix}n-1\\m\end{Bmatrix}+\begin{Bmatrix}n-1\\m-1\end{Bmatrix}(1\leqslant m\leqslant n-1)$,边界为$\begin{Bmatrix}n\\n\end{Bmatrix}=1(0\leqslant n),\begin{Bmatrix}n\\0\end{Bmatrix}=0(1\leqslant n)$
题解:第二类斯特林数表示把$n$个不相同的球放在$m$个相同的盒子里,没有空的盒子。可以枚举至少有几个空的盒子来容斥。
$$
\begin{Bmatrix}n\\m\end{Bmatrix}=\dfrac1{m!}\sum\limits_{i=0}^m\binom mi(-1)^i(m-i)^n
$$
直接带到原式子中
$$
\begin{align*}
&\sum\limits_{i=0}^n\sum\limits_{j=0}^i\begin{Bmatrix}i\\j\end{Bmatrix}\times2^j\times j!\\
=&\sum\limits_{i=0}^n\sum\limits_{j=0}^i\dfrac1{j!}\sum\limits_{k=0}^j\binom jk(-1)^k(j-k)^i\times2^j\times j!\\
=&\sum\limits_{i=0}^n\sum\limits_{j=0}^i\sum\limits_{k=0}^j\dfrac{j!}{k!(j-k)!}(-1)^k(j-k)^i\times2^j\\
=&\sum\limits_{i=0}^n\sum\limits_{j=0}^i2^jj!\sum\limits_{k=0}^j\dfrac{1}{k!(j-k)!}(-1)^k(j-k)^i\\
\end{align*}
$$
发现若$\begin{Bmatrix}n\\m\end{Bmatrix}$中$m>n$,值为$0$。可以把$j$的上界变为$n$
$$
\begin{align*}
=&\sum\limits_{i=0}^n\sum\limits_{j=0}^n2^jj!\sum\limits_{k=0}^j\dfrac{1}{k!(j-k)!}(-1)^k(j-k)^i\\
=&\sum\limits_{j=0}^n2^jj!\sum\limits_{k=0}^j\dfrac{(-1)^k}{k!}\dfrac{\sum\limits_{i=0}^n(j-k)^i}{(j-k)!}\\
=&\sum\limits_{j=0}^n2^jj!\sum\limits_{k=0}^j\dfrac{(-1)^k}{k!}\dfrac{(j-k)^{n+1}-1}{(j-k-1)(j-k)!}
\end{align*}
$$
令$f_i=\dfrac{(-1)^i}{i!},g_i=\dfrac{i^{n+1}-1}{(i-1)i!}$
$$
\begin{align*}
=&\sum\limits_{j=0}^n2^jj!\;[j](f*g)
\end{align*}
$$
$FFT$一下就好了
卡点:无
C++ Code:
#include <algorithm> #include <cstdio> #define maxn 262144 const int mod = 998244353; inline void reduce(int &x) { x += x >> 31 & mod; } namespace Math { inline int pw(int base, int p) { static int res; for (res = 1; p; p >>= 1, base = static_cast<long long> (base) * base % mod) if (p & 1) res = static_cast<long long> (res) * base % mod; return res; } inline int inv(int x) { return pw(x, mod - 2); } } namespace Poly { #define N maxn int lim, s, rev[N]; int Wn[N | 1]; inline void init(const int n) { lim = 1, s = -1; while (lim < n) lim <<= 1, ++s; for (int i = 1; i < lim; ++i) rev[i] = rev[i >> 1] >> 1 | (i & 1) << s; const int t = Math::pw(3, (mod - 1) / lim); *Wn = 1; for (register int *i = Wn; i != Wn + lim; ++i) *(i + 1) = static_cast<long long> (*i) * t % mod; } inline void FFT(int *A, const int op = 1) { for (register int i = 1; i < lim; ++i) if (i < rev[i]) std::swap(A[i], A[rev[i]]); for (register int mid = 1; mid < lim; mid <<= 1) { const int t = lim / mid >> 1; for (register int i = 0; i < lim; i += mid << 1) for (register int j = 0; j < mid; ++j) { const int X = A[i + j], Y = static_cast<long long> (A[i + j + mid]) * Wn[t * j] % mod; reduce(A[i + j] += Y - mod), reduce(A[i + j + mid] = X - Y); } } if (!op) { const int ilim = Math::inv(lim); for (register int *i = A; i != A + lim; ++i) *i = static_cast<long long> (*i) * ilim % mod; std::reverse(A + 1, A + lim); } } void Mul(int *A, int *B, int n) { init(n << 1); FFT(A), FFT(B); for (int i = 0; i < lim; ++i) A[i] = static_cast<long long> (A[i]) * B[i] % mod; FFT(A, 0); } #undef N } int n; int f[maxn], g[maxn]; int fac[maxn], inv[maxn], pinv[maxn]; int main() { scanf("%d", &n); fac[0] = fac[1] = inv[0] = inv[1] = pinv[0] = pinv[1] = 1; for (int i = 2; i <= n; ++i) { fac[i] = static_cast<long long> (fac[i - 1]) * i % mod; inv[i] = static_cast<long long> (mod - mod / i) * inv[mod % i] % mod; pinv[i] = static_cast<long long> (pinv[i - 1]) * inv[i] % mod; } g[0] = 1, g[1] = n + 1; for (int i = 2; i <= n; ++i) g[i] = static_cast<long long> (Math::pw(i, n + 1) - 1) * inv[i - 1] % mod * pinv[i] % mod; for (int i = 0; i <= n; ++i) f[i] = static_cast<long long> ((i & 1) ? mod - 1 : 1) * pinv[i] % mod; Poly::Mul(f, g, n + 1); for (int i = 0; i <= n; ++i) f[i] = static_cast<long long> (f[i]) * fac[i] % mod * Math::pw(2, i) % mod; int ans = 0; for (int i = 0; i <= n; ++i) reduce(ans += f[i] - mod); printf("%d\n", ans); return 0; }