标签:Pre prime int 题解 dfs leq maxn Order dp
题意
给定一个 \(1\) 到 \(N\) 的排列 \(P\),求 dfs 序为 \(P\) 且以 \(1\) 为根的有根树的数量(答案模 \(998244353\))
注意对于有多个子结点的结点,按编号从小到大遍历子结点。
\(2 \leq N \leq 500\)
思路
区间 dp。
考虑设 \(dp[l][r]\) 为以 \(P_l\) 到 \(P_r\) 组成,dfs 序为 \([P_l, P_r]\) 且以 \(P_l\) 为根的有根树数量。容易想到枚举最后遍历的子树区间 \([s, t]\),但是题目要求按编号升序遍历,因此难以判断合法性。
容易看到答案是 使 \([s, t]\) 添加后 dfs 序不变的有根树数量 $\times $ \([s, t]\) 组成的有根树数量。不妨考虑另外维护 \(dp^{\prime}[l][r]\) 表示将 \(P_{r + 1}\) 添加到以 \(P_l\) 为根,由 \([P_l, P_r]\) 组成的有根树后 dfs 序为 \([P_l, P_{r + 1}]\) 的方案数。易得:
\(dp[l, r] = \sum\limits_{l \leq k < r} dp^{\prime}[l][k] \times dp[k + 1][r]\)
$dp^{\prime}[l, r] = \sum\limits_{l \leq k < r, P_{k + 1} < P_{r + 1} dp^{\prime}[l][k] \times dp[k + 1][r]} $
边界条件是 \(dp[l][l] = dp^{\prime}[l][l] = 1\)
时间复杂度 \(O(n^3)\)
代码
#include <cstdio>
using namespace std;
const int maxn = 505;
const int mod = 998244353;
int n;
int p[maxn];
int dp[maxn][maxn][2];
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%d", &p[i]);
dp[i][i][0] = dp[i][i][1] = 1;
}
for (int l = 2; l <= n; l++)
{
for (int i = 1; i + l - 1 <= n; i++)
{
int j = i + l - 1;
for (int k = i; k <= j - 1; k++)
{
dp[i][j][0] = (dp[i][j][0] + (1ll * dp[i][k][1] * dp[k + 1][j][0])) % mod;
if (p[k + 1] < p[j + 1]) dp[i][j][1] = (dp[i][j][1] + (1ll * dp[i][k][1] * dp[k + 1][j][0])) % mod;
}
}
}
printf("%d\n", dp[1][n][0]);
return 0;
}
标签:Pre,prime,int,题解,dfs,leq,maxn,Order,dp 来源: https://www.cnblogs.com/lingspace/p/abc252g.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。