calc加强版

P5850 calc加强版

对于一个\(n\),答案就是 \(n! * [x^n]\prod^k_{i = 1} (1+ix)\)
乘积不好处理,求 \(\ln\) 转化成加法

\[\exp (\sum\ln(1+ix)) \]

\(\ln\) 定义可得

\[\ln(1+ix) = -\sum_{j\ge0} \frac{(-ix)^j}{j} \]

则原式为

\[\sum_{i = 1}^k\sum_{j\ge0} -\frac{(-ix)^j}{j} \]

\[\sum_{j\ge 0}\frac{(-1)^{j + 1} \sum_{i = 1}^k i^j}{j} x^j \]

处理自然数幂和是麻烦的,考虑用\(EGF\)求其值
\(F(x) = \sum_i (\sum_j j^i)\frac{x^i}{i!}\)

\[F(x) = \sum_j \sum_i \frac{(jx)^i}{i!} \]

\[F(x) = \sum_{j = 1}^k e^{jx} \]

\[F(x) = \frac{e^{k+1}-1}{e^x - 1} \]

多项式求逆即可,最后\(\exp\)回去。

Code
#include<cstdio>
#include<iostream>
#include<cstring>
#define IN inline
#define LL long long
using namespace std;
const int N = 5e5 + 5, P = 998244353, G = 3;
int n, a[N << 2], b[N << 2], inv[N << 2], K, fac[N];

LL fpow(LL x, LL y) {
	LL res = 1;
	for (; x; x >>= 1, y = y * y % P)
		if (x & 1) res = res * y % P;
	return res;
}
namespace Poly{
	int rev[N << 2], insF[N << 2], sginv[N << 2];
	void NTT(int *f, int len, int fl) {
		if (len == 1) return;
		for (int i = 0; i < len; i++)
			if (i < rev[i]) swap(f[i], f[rev[i]]);
		for (int l = 1; l < len; l <<= 1) {
			int I = fpow((P - 1) / (l << 1), G);
			if (fl == -1) I = fpow(P - 2, I);
			for (int i = 0; i < len; i += (l << 1)) {
				int W = 1;
				for (int j = 0; j < l; j++, W = (LL)W * I % P) {
					int x = f[i + j], y = (LL)f[i + j + l] * W % P;
					f[i + j] = (x + y) % P, f[i + j + l] = (x - y + P) % P;
				}
			}
		}
	}
	void Mulpoly(int *f, int *g, int lenF, int lenG) {  
		int len = 1, bit = 0;
		while (len <= lenF + lenG) len <<= 1, bit++;
		for (int i = 1; i < len; i++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << bit - 1);
		NTT(f, len, 1), NTT(g, len, 1);
		for (int i = 0; i < len; i++) f[i] = (LL)f[i] * g[i] % P;
		NTT(f, len, -1); int IV = fpow(P - 2, len);
		for (int i = 0; i <= lenF + lenG; i++) f[i] = (LL)f[i] * IV % P;
		for (int i = lenF + lenG + 1; i < len; i++) f[i] = 0;
	}
	void Invpoly(int *f, int lenF, int *g) { // [0, lenF)
		static int Flen[100]; int cnt = 0;
		for (int i = lenF; i > 1; i = i + 1 >> 1) Flen[++cnt] = i;
		for (int i = 1; i <= (cnt >> 1); i++) swap(Flen[i], Flen[cnt - i + 1]);	
		g[0] = fpow(P - 2, f[0]), Flen[0] = 1;
		for (int j = 1; j <= cnt; j++) {
			int len = 1, bit = 0;
			while (len < (Flen[j] << 1)) len <<= 1, bit++;
			for (int i = 1; i < len; i++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << bit - 1);
			for (int i = Flen[j - 1]; i < len; i++) g[i] = 0;
			
			for (int i = 0; i < Flen[j]; i++) insF[i] = f[i];
			for (int i = Flen[j]; i < len; i++) insF[i] = 0;
			
			NTT(g, len, 1), NTT(insF, len, 1);
			for (int i = 0; i < len; i++) g[i] = (LL)g[i] * (2LL - (LL)insF[i] * g[i] % P + P) % P;
			NTT(g, len, -1); int IV = fpow(P - 2, len);
			for (int i = 0; i < Flen[j]; i++) g[i] = (LL)g[i] * IV % P;
			if (j == cnt) for (int i = lenF; i < len; i++) g[i] = 0;
		}
	}
	void Getsginv(int len) {
		sginv[0] = sginv[1] = 1;
		for (int i = 2; i <= len; i++) sginv[i] = (LL)sginv[P % i] * (P - P / i) % P;
	}
	void Dpoly(int *f, int lenF) {
		for (int i = 0; i < lenF; i++) f[i] = (LL)f[i + 1] * (i + 1) % P;
	}
	void Jfpoly(int *f, int lenF) {
		for (int i = lenF; i >= 0; i--) f[i + 1] = (LL)f[i] * sginv[i + 1] % P;
		f[0] = 0;
	}
	void Lnpoly(int *f, int lenF) { // [0, lenF)
		static int Inv_f[N << 2];
		Invpoly(f, lenF, Inv_f), Dpoly(f, lenF - 1), Mulpoly(f, Inv_f, lenF - 1, lenF - 1), Jfpoly(f, lenF - 1);
		for (int i = lenF; i <= (lenF << 1); i++) f[i] = 0;
	}
	void Exppoly(int *f, int lenF, int *g) {
		static int s[N << 2];
		int limit = 1;
		while (limit < lenF) limit <<= 1;
		g[0] = 1;
		for (int len = 2; len <= limit; len <<= 1) {
			for (int i = 0; i < (len >> 1); i++) s[i] = g[i];
			for (int i = (len >> 1); i < len; i++) s[i] = 0;
			Lnpoly(s, len);
			for (int i = 0; i < len; i++) s[i] = (f[i] - s[i] + P) % P;
			s[0] = (s[0] + 1) % P;
			Mulpoly(g, s, len - 1, len - 1);
			for (int i = len; i < (len << 1); i++) g[i] = 0;
		}
		for (int i = lenF; i < limit; i++) g[i] = 0;
		for (int i = 0; i < limit; i++) s[i] = 0;
	}
}
IN int read() {
	int t = 0,res = 0; char ch = getchar();
	for (; !isdigit(ch); ch = getchar()) t |= (ch == '-');
	for (; isdigit(ch); ch = getchar()) res = (res << 3) + (res << 1) + (ch ^ 48);
	return t ? -res : res;
}
void write(int x) {
	if (!x) return; write(x / 10), putchar((x % 10) + '0');
}
int main() {
	K = read(), n = read(), Poly::Getsginv(n << 2), inv[0] = inv[1] = fac[0] = 1;
	for (int i = 2; i <= n + 5; i++) inv[i] = (LL)inv[i - 1] * Poly::sginv[i] % P;
	for (int i = 1; i <= n + 2; i++) fac[i] = (LL)fac[i - 1] * i % P;
	for (int i = 0; i <= n; i++) a[i] = inv[i + 1]; 
	Poly::Invpoly(a, n + 1, b), memset(a, 0, sizeof a);
	int tmp = 1;
	for (int i = 1; i <= n + 1; i++) tmp = (LL)tmp * (K + 1) % P, a[i - 1] = (LL)tmp * inv[i] % P;
	Poly::Mulpoly(a, b, n, n), memset(b, 0, sizeof b);
	for (int i = 1; i <= n; i++) a[i] = (LL)a[i] * fac[i - 1] % P;
	for (int i = 1; i <= n; i++) b[i] = (P + ((i & 1) ? 1 : -1) * a[i]) % P;
	memset(a, 0, sizeof a), Poly::Exppoly(b, n + 1, a);
	for (int i = 1; i <= n; i++) write((LL)a[i] * fac[i] % P), puts("");
}

posted @ 2023-03-15 21:51  RiverSheep  阅读(12)  评论(0编辑  收藏  举报