题解:AT_arc130_d [ARC130D] Zigzag Tree

题意:很简单了,不再赘述。

做法:

首先注意到对于相邻两个点,他们不能同时是极大点和极小点,考虑将这个设进状态。

因为是排列,所以很自然考虑经典 dp,设 \(dp_{i,j,0/1}\) 代表节点 \(i\),在子树中排名为 \(j\),是一个极大点 / 极小点。

枚举 \(v\) 中有多少个点插在 \(u\) 前面,有转移式:

\[dp_{u,i+j, 0}=C_{i+j-1}^jC_{sz_u-i + sz_v-j}^{sz_u-i}dp_{u,i,0}\sum_{t\le j}dp_{v, t, 1} \]

\[dp_{u,i+j, 1}=C_{i+j-1}^jC_{sz_u-i + sz_v-j}^{sz_u-i}dp_{u,i,1}\sum_{t\ge j + 1}dp_{v, t, 0} \]

对后面的提前计算前缀和转移即可。

代码实现因为是一年前写得,所以可能和上述转移式不同,大体相同。

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 3e3 + 5, mod = 998244353;
int C[maxn][maxn], n;
vector<int> e[maxn];
void prepare(int n) {
	C[0][0] = 1;
	for (int i = 1; i <= n; i++) {
		C[i][0] = 1;
		for (int j = 1; j <= i; j++)
			C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod;
	}
}
int dp[maxn][maxn][2], sz[maxn], pre[maxn], suf[maxn], g[maxn][2];
void dfs(int u, int fa) {
	dp[u][1][0] = dp[u][1][1] = 1;
	sz[u] = 1;
	for (int i = 0; i < e[u].size(); i++) {
		int v = e[u][i];
		if(v == fa)
			continue;
		dfs(v, u);
		for (int j = 0; j <= sz[v] + 1; j++)
			pre[j] = suf[j] = 0;
		for (int j = 1; j <= sz[v]; j++)
			pre[j] = pre[j - 1] + dp[v][j][0], pre[j] %= mod;
		for (int j = sz[v]; j >= 1; j--)
			suf[j] = suf[j + 1] + dp[v][j][1], suf[j] %= mod;
		for (int j = 1; j <= sz[u]; j++)
			for (int k = 0; k <= sz[v]; k++) {
				g[j + k][1] = (g[j + k][1] + dp[u][j][1] * C[j + k - 1][k] % mod * C[sz[v] - k + sz[u] - j][sz[v] - k] % mod * pre[k] % mod) % mod;
				g[j + k][0] = (g[j + k][0] + dp[u][j][0] * C[j + k - 1][k] % mod * C[sz[v] - k + sz[u] - j][sz[v] - k] % mod * suf[k + 1] % mod) % mod;
			}
		sz[u] += sz[v];
		for (int j = 0; j <= sz[u]; j++)
			dp[u][j][0] = g[j][0], dp[u][j][1] = g[j][1], g[j][0] = g[j][1] = 0;
	}
//	for (int i = 1; i <= sz[u]; i++)
//		cout << dp[u][i][0] << " " << dp[u][i][1] << endl;
//	cout << endl;
}
signed main() {
	cin >> n;
	prepare(n + 1);
	for (int i = 1; i < n; i++) {
		int x, y;
		cin >> x >> y;
		e[x].push_back(y);
		e[y].push_back(x);
	}
	dfs(1, 0);
	int ans = 0;
	for (int i = 1; i <= n; i++)
		ans = (ans + dp[1][i][0] + dp[1][i][1]) % mod;
	cout << ans << endl;
	return 0;
}
posted @ 2025-07-25 15:36  LUlululu1616  阅读(9)  评论(0)    收藏  举报