Progress Monitoring - CodeForces 509 F dp

本文探讨了如何构造一棵树,使得其深度优先搜索(DFS)遍历的序列为给定序列,并计算所有可能的树的数量。通过动态规划的方法解决了这一问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Progress Monitoring
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Programming teacher Dmitry Olegovich is going to propose the following task for one of his tests for students:

You are given a tree T with n vertices, specified by its adjacency matrix a[1... n, 1... n]. What is the output of the following pseudocode?

used[1 ... n] = {0, ..., 0};

procedure dfs(v):
    print v;
    used[v] = 1;
    for i = 1, 2, ..., n:
        if (a[v][i] == 1 and used[i] == 0):
            dfs(i);

dfs(1);

In order to simplify the test results checking procedure, Dmitry Olegovich decided to create a tree T such that the result is his favorite sequence b. On the other hand, Dmitry Olegovich doesn't want to provide students with same trees as input, otherwise they might cheat. That's why Dmitry Olegovich is trying to find out the number of different trees T such that the result of running the above pseudocode with T as input is exactly the sequence b. Can you help him?

Two trees with n vertices are called different if their adjacency matrices a1 and a2 are different, i. e. there exists a pair (i, j), such that 1 ≤ i, j ≤ n and a1[i][j] ≠ a2[i][j].

Input

The first line contains the positive integer n (1 ≤ n ≤ 500) — the length of sequence b.

The second line contains n positive integers b1, b2, ..., bn (1 ≤ bi ≤ n). It is guaranteed that b is a permutation, or in other words, each of the numbers 1, 2, ..., n appears exactly once in the sequence b. Also it is guaranteed that b1 = 1.

Output

Output the number of trees satisfying the conditions above modulo 109 + 7.

Sample test(s)
input
3
1 2 3
output
2
input
3
1 3 2
output
1

题意:构造深搜为给定序列的树,问有多少种可能性。

思路:dp[i][j]表示从i到j的以i为根节点的树有多少种,每次枚举k,dp[i][j]+=dp[i+1][k]+dp[k][j],也就是说,i下面的第一个子节点为i+1,然后因为dp[k][j]的子节点为有序的从k+1到j的点的排布方式,所以只要num[i+1]<num[k+1]即可。

AC代码如下:

#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
int num[510];
ll dp[510][510],MOD=1e9+7;
int main()
{
    int n,i,j,k;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
       scanf("%d",&num[i]);
    for(i=1;i<=n;i++)
       dp[i][i]=dp[i][i+1]=1;
    for(i=n;i>=1;i--)
       for(j=i+2;j<=n;j++)
          for(k=i+1;k<=j;k++)
            if(num[i+1]<num[k+1] || k==j)
              dp[i][j]=(dp[i][j]+dp[i+1][k]*dp[k][j])%MOD;
    printf("%I64d\n",dp[1][n]);
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值