AT_agc063_e Child to Parent 题解

AT_agc063_e Child to Parent 题解

\(c_x\) 表示点 \(x\) 一共执行的操作次数,对于不同的 \(c_x\) 序列最终的 \(A\) 序列是不同的,因此我们对 \(c_x\) 序列计数即可。

容易发现一个 \(c_x\) 合法的充要是 \(0\le c_x\le A_x+R\times \sum _{v\in son(x)} c_v\),但是我们不能把 \(c_x\) 记进状态里。

尝试设 DP \(f_x\) 表示子树 \(x\) 内的答案,假如我们求出了子树 \(x\) 内所有方案的 \(c_x\) 的和 \(g_x\),那么容易转移出 \(f_x\),有:

\[f_x=(A_x+1)(\prod_{v\in son(x)} f_v)+\sum _{v\in son(x)} g_v\prod _{w\in son(x)\setminus v} f_w \]

但是这个转移没有什么用,考虑设 \(f_{x,i}\) 表示子树 \(x\) 内所有方案的 \(c_x^i\) 的和,而方案数就相当于 \(f_{x,0}\),我们的最终答案即 \(f_{1,0}\)。可以写出转移(设 \(lim=A_x+R\times \sum c_v\)):

\[f_{x,i}=\sum _{所有方案} \sum _{t=0}^{lim} t^i \]

用第二类斯特林数将普通幂转下降幂,得:

\[\begin{aligned} f_{x,i} &= \sum _{所有方案} \sum _{t=0}^{lim} \sum _{j=0}^{i} {i\brace j}j!\binom {t}{j} \\ &= \sum _{所有方案} \sum _{j=0}^i {i\brace j} j!\sum _{t=0}^{lim} \binom{t}{j}\\ &= \sum _{所有方案} \sum _{j=0}^{i}{i\brace j} j!\binom {lim+1}{j+1} \\ &= \sum _{所有方案} \sum _{j=0}^{i} {i\brace j} \frac{(lim+1)^{\underline{j+1}}}{j+1} \end{aligned} \]

只需求出所有方案的 \((A_x+R\times \sum c_v+1)^{\underline {j+1}}\) 的和即可。拆出来是关于 \(\sum c_v\) 的多项式,而处理所有方案下 \((\sum c_v)^j\) 的和可以每次用二项式定理合并一个儿子。

复杂度是 \(O(n^3)\)

代码:

const int N=305,mod=998244353;
void inc(int &x,int y) {x+=y; if(x>=mod) x-=mod;}
void dec(int &x,int y) {if(x<y) x+=mod-y; else x-=y;}
int add(int x,int y) {return x+y>=mod ? x+y-mod : x+y;}
int sub(int x,int y) {return x<y ? x-y+mod : x-y;}
int mul(int x,int y) {return (ull) x*y%mod;}
int pow1(int x,int y) {
	int res=1;
	for(;y;y>>=1,x=mul(x,x)) if(y&1) res=mul(res,x);
	return res;
}
vi mul(const vi &x,const vi &y) {
	vi nw(Size(x)+Size(y)-1);
	fu(i,0,Size(x)) fu(j,0,Size(y)) inc(nw[i+j],mul(x[i],y[j]));
	return nw;
}
int str[N][N],C[N][N],inv[N];
int f[N][N],g[N],n,A[N],R;
vi G[N];
void dfs(int x) {
	f[x][0]=1;
	for(int v:G[x]) {
		dfs(v);
		memset(g,0,sizeof g);
		fo(i,0,n) {
			fo(j,0,i) {
				inc(g[i],mul(C[i][j],mul(f[x][j],f[v][i-j])));
			}
		}
		memcpy(f[x],g,sizeof g);
	}
	if(x==1) return;
	memset(g,0,sizeof g);
	vi p{1};
	fo(j,0,n) {
		p=mul(p,vi{sub(add(A[x],1),j),R});
		int s=0;
		fu(i,0,Size(p)) inc(s,mul(f[x][i],p[i]));
		s=mul(s,inv[j+1]);
		fo(i,j,n) inc(g[i],mul(str[i][j],s));
	}
	memcpy(f[x],g,sizeof g);
}

void init() {
	str[0][0]=1;
	fu(i,1,N) fu(j,1,N) str[i][j]=add(mul(str[i-1][j],j),str[i-1][j-1]);
	fu(i,0,N) C[i][0]=1;
	fu(i,1,N) fo(j,1,i) C[i][j]=add(C[i-1][j],C[i-1][j-1]);
	inv[0]=1;
	fu(i,1,N) inv[i]=mul(inv[i-1],i);
	inv[N-1]=pow1(inv[N-1],mod-2);
	fd(i,N-1,1) {
		int t=inv[i-1];
		inv[i-1]=mul(inv[i],i);
		inv[i]=mul(inv[i],t);
	}
}

void Main() {
	cin>>n;
	init();
	fo(i,2,n) {int p; cin>>p; G[p].pb(i);}
	cin>>R;
	fo(i,1,n) cin>>A[i];
	dfs(1);
	cout<<f[1][0]<<'\n';
}
posted @ 2025-11-16 19:13  dengchengyu  阅读(6)  评论(0)    收藏  举报