2021ICPC济南站 L. Strange Series 题解

2021ICPC济南站 L. Strange Series 题解

L. Strange Series

题意 ( 2   s 2\ \mathrm{s} 2 s)

给定一个 n n n次多项式 P ( x ) = a 0 + a 1 x + ⋯ + a n x n P(x)=a_0+a_1x+\cdots+a_nx^n P(x)=a0+a1x++anxn,其中 a i ≥ 0    ( i = 0 , ⋯   , n ) a_i\geq 0\ \ (i=0,\cdots,n) ai0  (i=0,,n).考察级数 S = ∑ m = 0 ∞ P ( m ) m ! \displaystyle S=\sum_{m=0}^\infty \dfrac{P(m)}{m!} S=m=0m!P(m).可以证明 S S S是良好定义的,且 S = p e S=p\mathrm{e} S=pe,其中 p p p是一个非负整数, e = ∑ m = 0 ∞ 1 m ! ≈ 2.71828 \displaystyle \mathrm{e}=\sum_{m=0}^\infty \dfrac{1}{m!}\approx 2.71828 e=m=0m!12.71828.求 p p p.

t    ( 1 ≤ t ≤ 100 ) t\ \ (1\leq t\leq 100) t  (1t100)组测试数据.每组测试数据输入一个整数 n    ( 0 ≤ n ≤ 1 e 5 ) n\ \ (0\leq n\leq 1\mathrm{e}5) n  (0n1e5).第二行输入 ( n + 1 ) (n+1) (n+1)个整数 a 0 , a 1 , ⋯   , a n    ( 0 ≤ a i < 998244353 ) a_0,a_1,\cdots,a_n\ \ (0\leq a_i<998244353) a0,a1,,an  (0ai<998244353).数据保证至多有 4 4 4组测试数据满足 n > 1000 n>1000 n>1000.

对每组测试数据,输出 p p p 998244353 998244353 998244353取模的结果.

思路

[引理] ∑ m = 0 ∞ m n m ! x m = e x ⋅ Q ( x ) \displaystyle\sum_{m=0}^\infty \dfrac{m^n}{m!}x^m=\mathrm{e}^x\cdot Q(x) m=0m!mnxm=exQ(x),其中 Q ( x ) Q(x) Q(x)是关于 x x x n n n次多项式.

[] 用数学归纳法证明.不妨设 n − 1 n-1 n1时结论成立.

∑ m = 0 ∞ 1 m ! ⋅ m n x m = x ∑ m = 0 ∞ 1 m ! ⋅ m n − 1 ⋅ m x m − 1 = x ∑ m = 0 ∞ 1 m ! ⋅ m n − 1 ⋅ d d x ( x m ) = x ⋅ d d x ∑ m = 0 ∞ 1 m ! ⋅ m n − 1 x m \displaystyle \sum_{m=0}^\infty \dfrac{1}{m!}\cdot m^nx^m=x\sum_{m=0}^\infty \dfrac{1}{m!}\cdot m^{n-1}\cdot mx^{m-1}=x\sum_{m=0}^\infty \dfrac{1}{m!}\cdot m^{n-1}\cdot\dfrac{\mathrm{d}}{\mathrm{d}x}(x^m)=x\cdot \dfrac{\mathrm{d}}{\mathrm{d}x}\sum_{m=0}^\infty \dfrac{1}{m!}\cdot m^{n-1} x^m m=0m!1mnxm=xm=0m!1mn1mxm1=xm=0m!1mn1dxd(xm)=xdxdm=0m!1mn1xm

= x ⋅ d d x [ e x Q ( x ) ] =x\cdot\dfrac{\mathrm{d}}{\mathrm{d}x}[\mathrm{e}^x Q(x)] =xdxd[exQ(x)],其中 Q ( x ) Q(x) Q(x)是关于 x x x ( n − 1 ) (n-1) (n1)次多项式.

注意到对 e x Q ( x ) \mathrm{e}^xQ(x) exQ(x)求导后多项式部分的最高次项仍为 x n − 1 x^{n-1} xn1,乘上前面的 x x x即证.

P ( x ) = a 0 + a 1 x + ⋯ + a n x n    ( a i ≥ 0 ) , S = ∑ m = 0 ∞ P ( m ) m ! = p e P(x)=a_0+a_1x+\cdots+a_nx^n\ \ (a_i\geq 0),\displaystyle S=\sum_{m=0}^\infty \dfrac{P(m)}{m!}=p\mathrm e P(x)=a0+a1x++anxn  (ai0),S=m=0m!P(m)=pe,则 p = 1 e S = 1 e lim ⁡ s → ∞ ∑ m = 0 s P ( m ) m ! \displaystyle p=\dfrac{1}{\mathrm{e}}S=\dfrac{1}{\mathrm{e}}\lim_{s\rightarrow\infty}\sum_{m=0}^s \dfrac{P(m)}{m!} p=e1S=e1slimm=0sm!P(m).

P ( m ) m ! = 1 m ! ( a 0 + a 1 m + ⋯ + a n m n ) = ∑ i = 0 n a i k i k ! \dfrac{P(m)}{m!}=\dfrac{1}{m!}(a_0+a_1m+\cdots+a_nm^n)=\displaystyle\sum_{i=0}^n a_i\dfrac{k^i}{k!} m!P(m)=m!1(a0+a1m++anmn)=i=0naik!ki,

​ 则 p = 1 e lim ⁡ s → ∞ ∑ m = 0 s ∑ i = 0 n a i m i m ! = ∑ i = 0 n a i ( 1 e lim ⁡ s → ∞ ∑ m = 0 s m i m ! ) = ∑ i = 0 n a i [ 1 e ∑ m = 0 ∞ m i m ! ] \displaystyle p=\dfrac{1}{\mathrm{e}}\lim_{s\rightarrow\infty}\sum_{m=0}^s \sum_{i=0}^n a_i\dfrac{m^i}{m!}=\sum_{i=0}^n a_i\left(\dfrac{1}{\mathrm{e}}\lim_{s\rightarrow\infty}\sum_{m=0}^s \dfrac{m^i}{m!}\right)=\sum_{i=0}^n a_i\left[\dfrac{1}{\mathrm{e}}\sum_{m=0}^\infty \dfrac{m^i}{m!}\right] p=e1slimm=0si=0naim!mi=i=0nai(e1slimm=0sm!mi)=i=0nai[e1m=0m!mi].

由引理知: ∑ m = 0 ∞ m i m ! x m = e x ⋅ Q ( x ) \displaystyle \sum_{m=0}^\infty \dfrac{m^i}{m!}x^m=\mathrm{e}^x\cdot Q(x) m=0m!mixm=exQ(x),其中 Q ( x ) Q(x) Q(x)是关于 x x x i i i次多项式,进而 p = ∑ i = 0 n a i ⋅ Q ( 1 ) \displaystyle p=\sum_{i=0}^n a_i \cdot Q(1) p=i=0naiQ(1),同时也证明了 p ∈ N p\in\mathbb{N} pN.

下面讨论如何求 Q ( x ) Q(x) Q(x)的系数.

i = 0 i=0 i=0时, ∑ m = 0 ∞ 1 m ! x m = e x ⋅ 1 \displaystyle \sum_{m=0}^\infty \dfrac{1}{m!}x^m=\mathrm{e}^x\cdot 1 m=0m!1xm=ex1,此时 Q ( x ) = 1 , Q ( 1 ) = 1 Q(x)=1,Q(1)=1 Q(x)=1,Q(1)=1.

i = 1 i=1 i=1时, ∑ m = 1 ∞ m m ! x m = e x ⋅ x \displaystyle \sum_{m=1}^\infty \dfrac{m}{m!}x^m=\mathrm{e}^x\cdot x m=1m!mxm=exx,此时 Q ( x ) = x , Q ( 1 ) = 1 Q(x)=x,Q(1)=1 Q(x)=x,Q(1)=1.

i = 2 i=2 i=2时, ∑ m = 1 ∞ m 2 m ! x m = e x ⋅ x ( x + 1 ) \displaystyle \sum_{m=1}^\infty \dfrac{m^2}{m!}x^m=\mathrm{e}^x\cdot x(x+1) m=1m!m2xm=exx(x+1),此时 Q ( x ) = x ( x + 1 ) , Q ( 1 ) = 2 Q(x)=x(x+1),Q(1)=2 Q(x)=x(x+1),Q(1)=2.

i = 3 i=3 i=3时, ∑ m = 1 ∞ m 3 m ! x m = e x ⋅ x ( x 2 + 3 x + 1 ) \displaystyle \sum_{m=1}^\infty \dfrac{m^3}{m!}x^m=\mathrm{e}^x\cdot x(x^2+3x+1) m=1m!m3xm=exx(x2+3x+1),此时 Q ( x ) = x ( x 2 + 3 x + 1 ) , Q ( 1 ) = 5 Q(x)=x(x^2+3x+1),Q(1)=5 Q(x)=x(x2+3x+1),Q(1)=5.

i = 4 i=4 i=4时, ∑ m = 1 ∞ m 4 m ! x m = e x ⋅ x ( x 3 + 6 x 2 + 7 x + 1 ) \displaystyle \sum_{m=1}^\infty \dfrac{m^4}{m!}x^m=\mathrm{e}^x\cdot x(x^3+6x^2+7x+1) m=1m!m4xm=exx(x3+6x2+7x+1),此时 Q ( x ) = x ( x 3 + 6 x 2 + 7 x + 1 ) , Q ( 1 ) = 15 Q(x)=x(x^3+6x^2+7x+1),Q(1)=15 Q(x)=x(x3+6x2+7x+1),Q(1)=15.

i = 5 i=5 i=5时, ∑ m = 1 ∞ m 5 m ! x m = e x ⋅ x ( x 4 + 10 x 3 + 25 x 2 + 15 x + 1 ) \displaystyle \sum_{m=1}^\infty \dfrac{m^5}{m!}x^m=\mathrm{e}^x\cdot x(x^4+10x^3+25x^2+15x+1) m=1m!m5xm=exx(x4+10x3+25x2+15x+1),

​ 此时 Q ( x ) = x ( x 4 + 10 x 3 + 25 x 2 + 15 x + 1 ) , Q ( 1 ) = 52 Q(x)=x(x^4+10x^3+25x^2+15x+1),Q(1)=52 Q(x)=x(x4+10x3+25x2+15x+1),Q(1)=52.

易联想到Bell数: B 0 = 1 , B 1 = 1 , B 2 = 2 , B 3 = 5 , B 4 = 15 , B 5 = 52 , ⋯ B_0=1,B_1=1,B_2=2,B_3=5,B_4=15,B_5=52,\cdots B0=1,B1=1,B2=2,B3=5,B4=15,B5=52,,它可用递推求得.

注意到 n n n最大为 1 e 5 1\mathrm{e}5 1e5,暴力递推出Bell数会TLE.考虑用Bell数的生成函数求Bell数.

Bell数的定义:将 n n n个不同的元素的集合划分为任意多个非空子集的方案数.

n n n个元素的方案数为 f n f_n fn.固定最后一个元素 x x x,枚举最后一个元素所在的集合的元素个数 i ∈ [ 1 , n ] i\in[1,n] i[1,n],从剩下的 ( n − 1 ) (n-1) (n1)个元素中选 ( i − 1 ) (i-1) (i1)个元素与 x x x在同一集合中,其他 ( n − i ) (n-i) (ni)个元素任意划分,故 f n = ∑ i = 1 n C n − 1 i − 1 ⋅ f n − i \displaystyle f_n=\sum_{i=1}^n C_{n-1}^{i-1}\cdot f_{n-i} fn=i=1nCn1i1fni,调整下标得 f n + 1 = ∑ i = 0 n C n i ⋅ f n − i \displaystyle f_{n+1}=\sum_{i=0}^n C_n^i\cdot f_{n-i} fn+1=i=0nCnifni.

f f f的EGF为 F ( x ) F(x) F(x),则 f n + 1 ( n + 1 ) ! = ∑ i = 0 n f n − i ( n − i ) ! ⋅ 1 i ! ( n + 1 ) \displaystyle \dfrac{f_{n+1}}{(n+1)!}=\sum_{i=0}^n \dfrac{f_{n-i}}{(n-i)!}\cdot\dfrac{1}{i!(n+1)} (n+1)!fn+1=i=0n(ni)!fnii!(n+1)1,进而 ( n + 1 ) ⋅ f n + 1 ( n + 1 ) ! = ∑ i = 0 n f n − i ( n − i ) ! ⋅ 1 i ! \displaystyle (n+1)\cdot\dfrac{f_{n+1}}{(n+1)!}=\sum_{i=0}^n \dfrac{f_{n-i}}{(n-i)!}\cdot\dfrac{1}{i!} (n+1)(n+1)!fn+1=i=0n(ni)!fnii!1,

​ 即 [ x n ] F ’ ( x ) = ∑ i = 0 n [ x n − i ] F ( x ) ⋅ [ x i ] e x \displaystyle [x^n]F’(x)=\sum_{i=0}^n [x^{n-i}]F(x)\cdot [x^i]\mathrm{e}^x [xn]F(x)=i=0n[xni]F(x)[xi]ex,亦即 F ′ ( x ) = F ( x ) e x F'(x)=F(x)\mathrm{e}^x F(x)=F(x)ex.

y = F ( x ) y=F(x) y=F(x),则 d y d x = e x y \dfrac{\mathrm{d}y}{\mathrm{d}x}=\mathrm{e}^xy dxdy=exy,移项得 d y y = e x d x \dfrac{\mathrm{d}y}{y}=\mathrm{e}^x\mathrm{d}x ydy=exdx,两边积分得 ln ⁡ y = e x + C \ln y=\mathrm{e}^x+C lny=ex+C,故 y = exp ⁡ ( e x + C ) y=\exp(\mathrm{e}^x+C) y=exp(ex+C).

n = 1 n=1 n=1时只有一种划分方案,代入得 C = − 1 C=-1 C=1,故 F ( x ) = exp ⁡ ( e x − 1 ) F(x)=\exp(\mathrm{e}^x-1) F(x)=exp(ex1).多项式exp求即可,时间复杂度 O ( n log ⁡ n ) O(n\log n) O(nlogn).

代码

const int MAXN = 6e5 + 5;
const int MOD = 998244353;

int rev[MAXN];  // rev[x]表示二进制数x镜像后的结果

void NTT(int* y, int lim, int op) {  // op=1时为NTT,op=-1时为INTT
	for (int i = 0; i < lim; i++)  // 做一遍BRP,将系数位置调整为递归后的位置
		if (rev[i] < i) swap(y[i], y[rev[i]]);

	for (int l = 2; l <= lim; l <<= 1) {  // 模拟合并过程,l为当前区间长度
		int g = qpow(3, (MOD - 1) / l, MOD);
		for (int i = 0; i < lim; i += l) {
			int cur = 1;
			int k = l >> 1;
			for (int j = 0; j < k; j++, cur = (ll)cur * g % MOD) {
				int tmp = (ll)y[i + j + k] * cur % MOD;
				y[i + j + k] = (y[i + j] - tmp + MOD) % MOD;  // 奇次项
				y[i + j] = ((ll)y[i + j] + tmp) % MOD;  // 偶次项
			}
		}
	}

	if (op == -1) {  // INTT
		reverse(y + 1, y + lim);
		int inv = qpow(lim, MOD - 2, MOD);
		for (int i = 0; i < lim; i++) y[i] = (ll)y[i] * inv % MOD;
	}
}

void PolyMul(int* a, int* b, int n, int m) {  // n次多项式a乘m次多项式b,结果放在a中
	int lim = 1, len = 0;
	while (lim < (n + m << 1)) lim <<= 1, len++;
	for (int i = 1; i < lim; i++) rev[i] = (rev[i >> 1] >> 1 | ((i & 1) << (len - 1)));

	NTT(a, lim, 1), NTT(b, lim, 1);
	for (int i = 0; i < lim; i++) a[i] = (ll)a[i] * b[i] % MOD;
	NTT(a, lim, -1);
}

int n;
int f[MAXN], derf[MAXN], invf[MAXN];  // f、f的导数、f的逆
int bell[MAXN];

int tmp[MAXN];  // 递归过程中临时存放系数的数组

void PolyInv(int deg, int* a, int* res) {
	if (deg == 1) {
		res[0] = qpow(a[0], MOD - 2, MOD);
		return;
	}

	PolyInv((deg + 1) >> 1, a, res);  // 递归求解

	int lim = 1, len = 0;
	while (lim < (deg << 1)) lim <<= 1, len++;

	for (int i = 1; i < lim; i++) rev[i] = (rev[i >> 1] >> 1 | ((i & 1) << (len - 1)));

	for (int i = 0; i < lim; i++) tmp[i] = a[i] * (i < deg);  // i≥deg的项在模意义下为0

	NTT(tmp, lim, 1), NTT(res, lim, 1);
	for (int i = 0; i < lim; i++)
		res[i] = (ll)(2 - (ll)tmp[i] * res[i] % MOD + MOD) % MOD * res[i] % MOD;
	NTT(res, lim, -1);

	for (int i = deg; i < lim; i++) res[i] = 0;  // i≥deg的项在模意义下为0
}

void PolyDer(int deg, int* a, int* res) {  // 对deg次多项式a求导,结果放在res中
	for (int i = 1; i < deg; i++) res[i - 1] = (ll)i * a[i] % MOD;
	res[deg - 1] = 0;
}

void PolyInt(int deg, int* a, int* res) {  // 对deg次多项式a求不定积分(C=0),结果放在res中
	res[0] = 0;
	for (int i = 1; i < deg; i++) res[i] = (ll)a[i - 1] * qpow(i, MOD - 2, MOD) % MOD;
}

void PolyLn(int n, int* a, int* res) {  // 对n次多项式a求ln,结果放在res中
	memset(derf, 0, so(derf));
	memset(invf, 0, so(invf));

	int deg = 1;
	while (deg <= n) deg <<= 1;

	PolyDer(deg, a, derf);  // a的导数
	PolyInv(deg, a, invf);  // a的逆
	PolyMul(derf, invf, deg, deg);
	PolyInt(deg, derf, res);
}

int lnres[MAXN];  // res的ln
int tmpa[MAXN];  // 递归过程中临时存放系数的数组

void PolyExp(int deg, int* a, int* res) {  // 对deg次多项式a求exp,结果放在res中
	if (deg == 1) {
		res[0] = 1;
		return;
	}

	PolyExp(deg + 1 >> 1, a, res);

	PolyLn(deg, res, lnres);

	int lim = 1, len = 0;
	while (lim < (deg << 1)) lim <<= 1, len++;
	for (int i = 1; i < lim; i++) rev[i] = (rev[i >> 1] >> 1 | ((i & 1) << (len - 1)));

	for (int i = 0; i < deg; i++) tmpa[i] = a[i];
	for (int i = deg; i < lim; i++) tmpa[i] = lnres[i] = 0;
	for (int i = 0; i < lim; i++) tmpa[i] = (((ll)tmpa[i] - lnres[i]) % MOD + MOD) % MOD;
	tmpa[0]++;

	NTT(tmpa, lim, 1), NTT(res, lim, 1);
	for (int i = 0; i < lim; i++) res[i] = (ll)res[i] * tmpa[i] % MOD;
	NTT(res, lim, -1);
	for (int i = deg; i < lim; i++) res[i] = 0;
}

int fac[MAXN], ifac[MAXN];

void init() {  // 预处理Bell数
	fac[0] = 1;
	for (int i = 1; i < MAXN; i++) fac[i] = (ll)fac[i - 1] * i % MOD;

	ifac[MAXN - 1] = qpow(fac[MAXN - 1], MOD - 2, MOD);
	for (int i = MAXN - 1; i; i--) ifac[i - 1] = (ll)ifac[i] * i % MOD;

	n = 1e5 + 1;
	for (int i = 1; i < n; i++) f[i] = ifac[i];

	PolyExp(n, f, bell);

	for (int i = 0; i < n; i++) bell[i] = (ll)bell[i] * fac[i] % MOD;
}

int main() {
	init();  // 预处理Bell数
	
	CaseT{
		int n; cin >> n;
		int ans = 0;
		for (int i = 0; i <= n; i++) {
			int a; cin >> a;
			ans = ((ll)ans + (ll)a * bell[i]) % MOD;
		}
		cout << ans << endl;
	}
}


你可能感兴趣的:(2022ACM暑假训练,算法)