BZOJ3684 大朋友与多叉树(拉格朗日反演)

BZOJ3684 大朋友与多叉树(拉格朗日反演)

题目大意

我们的大朋友很喜欢计算机科学,而且尤其喜欢多叉树。对于一棵带有正整数点权的有根多叉树,如果它满足这样的性质,我们的大朋友就会将其称作神犇的:点权为1的结点是叶子结点;对于任一点权大于1的结点u,u的孩子数目deg[u]属于集合D,且u的点权等于这些孩子结点的点权之和。
给出一个整数s,你能求出根节点权值为s的神犇多叉树的个数吗?请参照样例以更好的理解什么样的两棵多叉树会被视为不同的。
我们只需要知道答案关于950009857(453*2^21+1,一个质数)取模后的值。

数据范围

1<=m<s<=10^5, 2<=d[i]<=s

解题思路

拉格朗日反演经典题

写出递推式

\[T(x) = x+\sum_{i\in S}T(x)^i \]

使用拉格朗日反演

\[x = T(x)-\sum_{i \in S}T(x)^i \]

\(G(x)=T(x)\)\(F(x)=x-\sum_{i\in S}x^i\)

\(F(G(X)) = x\),所以可以直接求出 \([x^n]G(x)=\frac 1n[x^{n-1}]{\left(\frac{x}{F(x)}\right)}^n\)

代码

#include <queue>
#include <vector>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MP make_pair
#define ll long long
#define fi first
#define se second
using namespace std;

template <typename T>
void read(T &x) {
    x = 0; bool f = 0;
    char c = getchar();
    for (;!isdigit(c);c=getchar()) if (c=='-') f=1;
    for (;isdigit(c);c=getchar()) x=x*10+(c^48);
    if (f) x=-x;
}

template<typename F>
inline void write(F x, char ed = '\n')
{
	static short st[30];short tp=0;
	if(x<0) putchar('-'),x=-x;
	do st[++tp]=x%10,x/=10; while(x);
	while(tp) putchar('0'|st[tp--]);
	putchar(ed);
}

template <typename T>
inline void Mx(T &x, T y) { x < y && (x = y); }

template <typename T>
inline void Mn(T &x, T y) { x > y && (x = y); }

const int N = 333400;
const int P = 950009857;
int r[N], lim, n;
ll A[N], B[N], C[N], D[N], E[N], f[N], g[N];
ll inv[N];

void init(void) {
	inv[0] = inv[1] = 1;
	for (int i = 2;i <= 2 * n; i++)
		inv[i] = inv[P % i] * (P - P / i) % P;
}

ll fpw(ll x, ll mi) {
	ll res = 1;
	for (; mi; mi >>= 1, x = x * x % P)
		if (mi & 1) res = res * x % P;
	return res;
}

void NTT(ll *a, int ty) {
	for (int i = 0;i < lim; i++)
		if (r[i] > i) swap(a[i], a[r[i]]);
	for (int i = 1;i < lim; i <<= 1) {
		ll wn = fpw(7, (P - 1) / (i << 1));
		for (int j = 0;j < lim; j += (i << 1)) {
			ll w = 1;
			for (int k = 0;k < i; k++, w = w * wn % P) {
				ll x = a[j+k], y = a[i+j+k] * w % P;
				a[j+k] = (x + y) % P, a[i+j+k] = (x - y + P) % P;
			}
		}
	}
	if (ty == -1) {
		ll inv = fpw(lim, P - 2);
		for (int i = 0;i < lim; i++)
			a[i] = a[i] * inv % P;
		reverse(a + 1, a + lim);
	}
}


/*

F(G) - A = 0;
F(G0) - A = 0;
0 = T(G0)+T(G0)'(G-G0)
G = G0-T(G0)/T(G0)'

1/G0 - A = 0;

G = G0 + (1/G0-A)G0^2
G = G0 + G0 - G0^2A
G = G0(2 - A*G0)

*/

void Inv(ll *a, ll *b, int deg) {
	b[0] = fpw(a[0], P - 2); int len;
	for (len = 2;len < (deg << 1); len <<= 1) {
		lim = len << 1;
		for (int i = 1;i < lim; i++)
			r[i] = (r[i>>1]>>1) | ((i & 1) ? len : 0);
		for (int i = 0;i < len; i++) A[i] = a[i], B[i] = b[i];
		NTT(A, 1), NTT(B, 1);
		for (int i = 0;i < lim; i++)
			b[i] = (2 + (P - A[i]) * B[i]) % P * B[i] % P;
		NTT(b, -1);
		for (int i = len;i < lim; i++) b[i] = 0;
	}
    for (int i = 0;i < len; i++) A[i] = B[i] = 0;
}

void chick(ll *a, int deg) {
	for (int i = deg - 1;i >= 1; i--)
		a[i] = a[i-1] * inv[i] % P;
	a[0] = 0;
}

void door(ll *a, int deg) {
	for (int i = 1;i < deg; i++)
		a[i-1] = a[i] * i % P;
	a[deg - 1] = 0;
}

void Ln(ll *a, int deg) {
	Inv(a, C, deg), door(a, deg);
	NTT(a, 1), NTT(C, 1);
	for (int i = 0;i < lim; i++)
		a[i] = a[i] * C[i] % P;
	NTT(a, -1), chick(a, deg);
}

/*

F(G) - A = 0;
F(G0) - A = 0;
0 = T(G0)+T(G0)'(G-G0)
G = G0-T(G0)/T(G0)'

1/G0 - A = 0;

G = G0 + (LnG0-A)G0
G = -(-1+LnG0-A)G0

*/

void Exp(ll *a, ll *b, int deg) {
	b[0] = 1; int len;
	for (len = 2;len < (deg << 1); len <<= 1) {
		lim = len << 1;
		for (int i = 0;i < len; i++) D[i] = b[i];
		Ln(D, len); D[0] = (a[0] + 1 - D[0] + P) % P;
		for (int i = 1;i < len; i++)
			D[i] = (a[i] - D[i] + P) % P;
		NTT(D, 1), NTT(b, 1);
		for (int i = 0;i < lim; i++)
			b[i] = b[i] * D[i] % P;
		NTT(b, -1);
		for (int i = len;i < lim; i++) b[i] = 0;
	}
}

ll G[N];
void lage() {
	Inv(f, E, n), Ln(E, n);
	for (int i = 0;i < n; i++) 
		E[i] = E[i] * n % P;
	Exp(E, G, n);
}

int m;
int main() {
	read(n), read(m), init(); f[0] = 1;
	for (int i = 0, t;i < m; i++) read(t), f[t-1] += P - 1;
	lage();
	write(G[n-1] * inv[n] % P);
	return 0;
}
posted @ 2020-07-29 14:59  Hs-black  阅读(107)  评论(0编辑  收藏  举报