首页 > 其他分享 >P5219 无聊的水题 I

P5219 无聊的水题 I

时间:2023-03-15 21:55:05浏览次数:36  
标签:lenF 水题 无聊 s2 s1 ++ P5219 int len

P5219 无聊的水题 I

计有标号树,容易想到 \(\text{Prufer}\) 序列,那么对于度数的限制即使,每一个数的出现次数要小于等于\(m - 1\),且一定要有等于的,容斥一下,用小于等于 \(m-1\) 答案减去小于等于 \(m - 2\) 即可。
对于一种数 \(i\),设其\(EGF\)为

\[F(x) = \sum_{i=0}^{m - 1}\frac{x^i}{i!} \]

那么答案即为

\[(n - 2)![x^{n - 2}]F^n(x) \]

多项式快速幂即可,时间复杂度\(O(n\log n)\)

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

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;
}
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;
}
const int invG = fpow(P - 2, G);
namespace Poly{
	int rev[N << 2], insF[N << 2], sginv[N << 2];
	void NTT(int *f, int len, int fl) {
		static int W[N << 2] = {1};
		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), fl == 1 ? G : invG);
			for (int i = 1; i < l; i++) W[i] = (LL)W[i - 1] * I % P;
			for (int i = 0; i < len; i += (l << 1))
				for (int j = 0; j < l; j++) {
					int x = f[i | j], y = (LL)f[i | j | l] * W[j] % P;
					f[i | j] = (x + y >= P ? x + y - P : x + y);
					f[i | j | l] = (x - y < 0 ? x - y + P : x - y);
				}
		} 
		if (fl == -1) {
			int IV = fpow(P - 2, len);
			for (int i = 0; i < len; i++) f[i] = (LL)f[i] * IV % 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);
		for (int i = lenF + 1; i < len; i++) f[i] = 0;
		for (int i = lenG + 1; i < len; i++) g[i] = 0;
		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);
		for (int i = lenF + lenG + 1; i < len; i++) f[i] = 0;
	}
	void Invpoly(int *f, int lenF, int *g) { // [0, lenF);
		static int s2[N << 2], s1[N << 2];
		int limit = 1; while (limit < lenF) limit <<= 1;
		g[0] = fpow(P - 2, f[0]);
		for (int len = 2, bit = 1; len <= limit; len <<= 1, bit++) {
			for (int i = 1; i < len; i++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << bit - 1);
			for (int i = 0; i < (len >> 1); i++) s2[i] = g[i];
			for (int i = (len >> 1); i < len; i++) s2[i] = 0;
			for (int i = 0; i < len; i++) s1[i] = f[i];
			NTT(s2, len, 1), NTT(s1, len, 1);
			for (int i = 0; i < len; i++) s1[i] = (LL)s2[i] * s1[i] % P;
			NTT(s1, len, -1);
			for (int i = 0; i < (len >> 1); i++) s1[i] = 0;
			
			NTT(s1, len, 1);
			for (int i = 0; i < len; i++) s1[i] = (LL)s1[i] * s2[i] % P;
			NTT(s1, len, -1);
			for (int i = (len >> 1); i < len; i++) g[i] = (s1[i] == 0 ? 0 : P - s1[i]);
		}
		for (int i = lenF; i < limit; i++) g[i] = 0;
		for (int i = 0; i < limit; i++) s2[i] = s1[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;
		f[lenF] = 0;
	}
	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 << 2); i++) f[i] = 0;
	}
	void Exppoly(int *f, int lenF, int *g) { // [0, lenF)
		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 = (len >> 1); i < len; i++) g[i] = 0;
			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 = lenF; i < limit; i++) g[i] = 0;
		for (int i = 0; i < limit; i++) s[i] = 0;
	}
}
int solve(int x) {
	if (!x) return 0;
	memset(a, 0, sizeof a), memset(b, 0, sizeof b);
	for (int i = 0; i <= x; i++) a[i] = inv[i];
	Poly::Lnpoly(a, n - 1);
	for (int i = 0; i < n - 1; i++) a[i] = (LL)n * a[i] % P;
	Poly::Exppoly(a, n - 1, b);
	return b[n - 2];
}
int main() {
	n = read(), m = read(), Poly::Getsginv(n << 1), inv[0] = inv[1] = 1;
	for (int i = 2; i <= m; i++) inv[i] = (LL)inv[i - 1] * Poly::sginv[i] % P; 
	int fac = 1;
	for (int i = 2; i <= n - 2; i++) fac = (LL)fac * i % P;
	printf("%d\n", (LL)fac * (solve(m - 1) - solve(m - 2) + P) % P);
}

标签:lenF,水题,无聊,s2,s1,++,P5219,int,len
From: https://www.cnblogs.com/nibabadeboke/p/17220252.html

相关文章