HNOI2010 合唱队

为获得更好的阅读体验请访问我的 Blog

Luogu

这应该又是一道 HNOI 的普及 DP 吧。。。

可以发现,每次插入后都将是一个连续的区间,所以就是区间 DP 辣

\(f(i,j,0)\) 为区间 \([i,j]\) 最后一个推进 \(i\) 的方案数,\(f(i,j,1)\) 为最后一个推进 \(j\)
\[ \begin{cases} f(i,j,0) = f(i + 1,j,0) + f(i + 1,j,1) & A_i < A_{i + 1}\;and\;A_i < A_j \\ f(i,j,1) = f(i,j - 1,1) + f(i,j - 1, 0) & A_r > A_{r - 1} \;and\;A_r > A_l \end{cases} \]
最终答案就是 \(f(1,n,0)+f(1,n,1)\)

边界条件只要将区间长度为 \(2\) 的情况特判下就行了。

#include <iostream>
#include <cstdio>

const int Mod = 19650827;
const int MaxN = 1000 + 5;

int N;
int A[MaxN], Dp[MaxN][MaxN][2];

inline int read()
{
    register int x = 0;
    register char ch = getchar();
    while(!isdigit(ch)) ch = getchar();
    while(isdigit(ch))
    {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x;
}

int main()
{
    N = read();
    for(int i = 1; i <= N; ++i) A[i] = read();
    for(int len = 2; len <= N; ++len)
    {
        for(int l = 1; l + len - 1 <= N; ++l)
        {
            int r = l + len - 1;
            if(len == 2)
            {
                if(A[l] < A[r]) Dp[l][r][0] = Dp[l][r][1] = 1;
                continue;
            }
            if(A[l] < A[l + 1]) Dp[l][r][0] += Dp[l + 1][r][0];
            if(A[l] < A[r]) Dp[l][r][0] += Dp[l + 1][r][1];
            Dp[l][r][0] %= Mod;
            if(A[r] > A[r - 1]) Dp[l][r][1] += Dp[l][r - 1][1];
            if(A[r] > A[l]) Dp[l][r][1] += Dp[l][r - 1][0];
            Dp[l][r][1] %= Mod;
        }
    }
    printf("%d\n", (Dp[1][N][0] + Dp[1][N][1]) % Mod);
    return 0;
}

转载于:https://www.cnblogs.com/zcdhj/p/9396509.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值