1 条题解

  • 0
    @ 2025-8-24 22:16:22

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar lxy
    **

    搬运于2025-08-24 22:16:22,当前版本为作者最后更新于2023-01-09 16:40:57,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    更好的阅读体验

    分析

    一个妙妙的 trick。

    首先原题可以转化成求有多少 1n1 \sim n 的排列 pp 满足 i(1,n)\forall i\in(1,n)pip_i 两边的数同时小于或大于 pip_i,且 p1=s,pn=tp_1=s,p_n=t。这类题都可以采用插入法 dp。

    首先设状态,dpi,jdp_{i,j} 表示前 ii 个数,分成 jj 段的方案数。从小到大加入每一个数,考虑现在枚举到 ii,若 isi \neq siti\neq t,则可以分三种情况讨论:

    1. 新开一段

      由于后加入的一定比 ii 大,所以以后插入在 ii 两边的数一定比 ii 大,所以总是合法。此时上一步操作完有 j1j-1 段,所以有 (j1)+1=j(j-1)+1=j 个空可以放。但是如果 i>si>s 说明头不能放,同理 i>ti>t 说明尾不能放。因此有转移:

      dpi,j=(j[i>s][i>t])×dpi1,j1dp_{i,j}=(j-[i>s]-[i>t]) \times dp_{i-1,j-1}
    2. 接在某一段头/尾

      这样的话以后一定会有一个 >i>i 的数接在 ii 另一侧,ii 两侧就有一个大于它的和一个小于它的,与题意不符,所以不会有这种情况。

    3. 将两段连起来

      此时 ii 两侧的都比它小,与题意相符。上一步操作完有 j+1j+1 段,有 j+11=jj+1-1=j 个空可以插,因此有转移:

      dpi,j=j×dpi1,j+1dp_{i,j}=j\times dp_{i-1,j+1}

    最后一定是整体一段,故答案为 dpn,1dp_{n,1}

    核心代码

    const int MAXN=2e3+7;
    const int mod=1e9+7;
    int n,s,t,dp[MAXN][MAXN];
    signed main(){
        qread(n,s,t);int i,j;dp[1][1]=1;
        for(i=2;i<=n;i++){
            for(j=1;j<=i;j++){
                if(i!=s&&i!=t) dp[i][j]=(j*(dp[i-1][j+1])%mod+(j-(i>s)-(i>t))*dp[i-1][j-1]%mod)%mod;
                else dp[i][j]=dp[i-1][j-1]+dp[i-1][j];
            }
        }printf("%lld\n",dp[n][1]);
        return 0;
    }
    
    • 1

    信息

    ID
    5006
    时间
    1000ms
    内存
    125MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者