JZOJ6414 【NOIP2019模拟11.07】子树问题(subtree)

题目描述:
JZOJ6414 【NOIP2019模拟11.07】子树问题(subtree)_第1张图片

输入:
JZOJ6414 【NOIP2019模拟11.07】子树问题(subtree)_第2张图片

输出:
输出到文件 subtree.out 中。
输出用单个空格隔开的 R L + 1 个整数,依次表示深度为 L, L + 1, . . . , R 的好的Yazid 树数目对 998, 244, 353 取模的结果。

这道题考场看都没看,所以这里补个题目大意吧。
这道题是让你求有 N N N个点满足题意且深度为 L L L~ R R R的树的个数。

然后可以设出 D P DP DP f i , j f_{i,j} fi,j表示 i i i个点,树深度不超过 j j j的树的棵数。
可得转移: f i , j = Σ k = 1 k < i f i − k , j ∗ f k , j − 1 ∗ C k − 1 i − 2 f_{i,j}=\Sigma_{k=1}^{kfi,j=Σk=1k<ifik,jfk,j1Ck1i2

注意下如果 k k k a a a中的元素,那么哪种方案贡献为 0 0 0

很显然是吧?我并不觉得,毕竟考场没推出来。

/*
	事已至此,只能膜拜2017张晋杰大佬。
	stO 张晋杰 Orz 
*/
#include 
#include 
using namespace std;

const int N = 510;
const int mod = 998244353;

inline void read(int &x)
{
	char ch = getchar(); x = 0;
	for(;ch < '0' || ch > '9';) ch = getchar();
	for(;ch >= '0' && ch <= '9';) x = x * 10 + (ch ^ '0'), ch = getchar();
}

int f[N][N],n,k,fac[N] = {1},inv[N],L,R,buc[N],a[N];

int f_pow(int a,int x)
{
	int ret = 1;
	for(;x;x >>= 1) (x & 1) && (ret = 1ll * ret * a % mod), a = 1ll * a * a % mod;
	return ret % mod;
}

int C(int x,int y) { return 1ll * fac[x] * inv[x - y] % mod * inv[y] % mod; }

int main()
{
	freopen("subtree.in","r",stdin);
	freopen("subtree.out","w",stdout); 
	
	read(n), read(k);
	for(int i = 1;i <= k; ++ i) read(a[i]), buc[a[i]] = 1;
	read(L), read(R);
	
	for(int i = 1;i < N; ++ i) fac[i] = 1ll * fac[i - 1] * i % mod;
	inv[N - 1] = f_pow(fac[N - 1],mod - 2);
	for(int i = N - 1;i; -- i) inv[i - 1] = 1ll * inv[i] * i % mod;
	
	for(int i = 1;i <= n; ++ i) f[1][i] = 1;
	for(int i = 2;i <= n; ++ i)
		for(int j = 1;j <= n; ++ j)
			for(int k = 1;k < i; ++ k) 
				if(!buc[k]) f[i][j] = (f[i][j] + 1ll * f[i - k][j] * f[k][j - 1] % mod * C(i - 2,k - 1) % mod) % mod;
				
	for(int i = L;i <= R; ++ i) printf("%d ",!buc[n] ? (f[n][i] - f[n][i - 1] + mod) % mod : 0);
	fclose(stdin); fclose(stdout);
	return 0;
} 

Z J J ZJJ ZJJ在改完题后把全机房嘲讽了一遍。

事已至此,只能膜拜2017张晋杰。
stO 张晋杰 Orz

你可能感兴趣的:(CSP赛前集训,好题)