【LG4091】[HEOI2016/TJOI2016]求和


【LG4091】[HEOI2016/TJOI2016]求和

题面

要你求:

\[\sum_{i=0}^n\sum_{j=0}^iS(i,j)*2^j*j! \]

其中\(S\)表示第二类斯特林数,\(n\leq10^5\),答案对\(998244353\)取模。

题解

这题你们好早就做了,因为由于技术原因(不会\(NTT\)),我现在才做,我真是菜爆了。

先来推柿子:

\(\because S(i,j)=0(i < j)\)

\(\therefore\;\)原式\(=\sum_{i=0}^n\sum_{j=0}^nS_i^j*2^j*j!\)

\(2^j*j!\)提到前面:

\[\sum_{j=0}^n2^j*(j!)\sum_{i=0}^nS_i^j \]

\(\because\;S_n^m=\frac {1}{m!}(-1)^iC_m^i(m-i)^n\)

\(\therefore S_n^m=\sum_{i=0}^m\frac {(-1)^i}{i!}\frac {(m-i)^n}{(m-i)!}\)

那么原式\(=\)

\[\sum_{j=0}^n2^j*j!\sum_{i=0}^n\sum_{k=0}^j\frac {(-1)^k}{k!}\frac {(j-k)^i}{(j-k)!}\\ \Leftrightarrow \sum_{j=0}^n2^j*j!\sum_{k=0}^j\frac {(-1)^k}{k!}\frac {\sum_{i=0}^n(j-k)^i}{(j-k)!}\\ \]

然后发现其实后面那一坨是

\[f(i)=\frac {(-1)^i}{i!}\\ g(i)=\frac {\sum_{j=0}^ni^j}{i!}=\frac {i^{n+1}-1}{(i-1)i!} \]

的卷积,直接\(NTT\)搞就好了。

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring> 
#include <cmath> 
#include <algorithm>
using namespace std; 
const int Mod = 998244353; 
int fpow(int x, int y) { 
	int res = 1; 
	while (y) {
		if (y & 1) res = 1ll * res * x % Mod; 
		x = 1ll * x * x % Mod; 
		y >>= 1; 
	}
	return res; 
} 
const int G = 3, iG = fpow(G, Mod - 2);
const int MAX_N = 3e5 + 5; 
int Limit, rev[MAX_N]; 
void NTT(int *p, int op) { 
	for (int i = 0; i < Limit; i++) if (i < rev[i]) swap(p[i], p[rev[i]]); 
	for (int i = 1; i < Limit; i <<= 1) {
		int rot = fpow(op == 1 ? G : iG, (Mod - 1) / (i << 1)); 
		for (int j = 0; j < Limit; j += (i << 1)) { 
			int w = 1; 
			for (int k = 0; k < i; k++, w = 1ll * w * rot % Mod) { 
				int x = p[j + k], y = 1ll * w * p[i + k + j] % Mod; 
				p[j + k] = (x + y) % Mod, p[i + j + k] = (x - y + Mod) % Mod; 
			} 
		} 
	}
	if (op == -1) {
		int inv = fpow(Limit, Mod - 2); 
		for (int i = 0; i < Limit; i++) p[i] = 1ll * p[i] * inv % Mod;
	} 
} 
int N, f[MAX_N], g[MAX_N]; 
int main () {
#ifndef ONLINE_JUDGE 
	freopen("cpp.in", "r", stdin); 
#endif 
	cin >> N; f[0] = 1, g[0] = 1; 
	for (int i = 1, fac = 1; i <= N; fac = 1ll * fac * (++i) % Mod) { 
		f[i] = (1ll * ((i & 1) ? -1 : 1) * fpow(fac, Mod - 2) % Mod + Mod) % Mod; 
		g[i] = 1ll * (fpow(i, N + 1) + Mod - 1) % Mod * fpow(1ll * (i - 1) * fac % Mod, Mod - 2) % Mod; 
	}
	g[1] = N + 1; 
	int p = 0; 
	for (Limit = 1; Limit <= (N << 1); Limit <<= 1, ++p) ;
	for (int i = 0; i < Limit; i++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (p - 1)); 
	NTT(f, 1), NTT(g, 1); 
	for (int i = 0; i < Limit; i++) f[i] = 1ll * f[i] * g[i] % Mod;
	NTT(f, -1); 
	int ans = 0, fac = 1, pw = 1; 
	for (int i = 0; i <= N; i++, fac = 1ll * fac * i % Mod, pw = 2ll * pw % Mod)
		ans = (ans + 1ll * fac * pw % Mod * f[i] % Mod) % Mod; 
	printf("%d\n", ans); 
	return 0; 
} 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM