首页 > 其他分享 >P5999 [CEOI2016] kangaroo

P5999 [CEOI2016] kangaroo

时间:2024-05-19 18:07:23浏览次数:31  
标签:插入 kangaroo P5999 CEOI2016 leq MAXN ll dp MOD

题目大意

求出有多少种排列 \(p\) 满足对于任意 \(i\in (1,n)\) 有 \(p_i\) 两侧的值同时大于或小于 \(p_i\)。规定 \(p_1=s,p_n=t\)。
\(2\leq n\leq 2\times 10^3,1\leq s,t\leq n\)

思路

首先能看出是动态规划。但是如果纯区间动规的话不太好转移,因为无法使得两个区间拼接的部分仍然满足大小的关系。这时我们考虑一种 trick。考虑 \(dp[i][j]\) 表示插入 \([1,i]\),并将序列分成了 \(j\) 段,满足每一段的合法性。且要求每一次操作任意一段均为合法。

所以考虑:

  1. 将 \(i\) 插入到原来的块里。可这样后续的插入会有一种方案插在 \(i\) 的一侧,这样这个就又大又小不符合题意了。
  2. 新增一个块。
    这个显然可以,因为一个块里只有它自己。然后以前 \(j-1\) 个块新增一个所以插 \(j\) 个空。
    \(f[i][j]=f[i-1][j-1]\cdot j\)
  3. 合并原来两个块。
    这个也显然可以因为以前插入的块的元素都小于 \(i\) 所以自然符合规定。具体实现类似上文只不过不能插两端。
    \(f[i][j]=f[i-1][j+1]\cdot j\)

之后特判一下 \(s,t\) 即可,也就是说另起一段还是插在原来已经 \(j\) 个段的头里。然后就是如果已经有 \(s\) 就不能新开在最左边,如果有 \(t\) 就不能开在最右边。

代码

#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
const ll MAXN=2e3+5;
const ll MOD=1e9+7;
ll n,s,t;
ll dp[MAXN][MAXN];
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n>>s>>t;
    dp[1][1]=1;
    for(int i=2;i<=n;++i){
        for(int j=1;j<=i;++j){
            if(i==s||i==t){
                dp[i][j]=dp[i-1][j-1]+dp[i-1][j];
                dp[i][j]%=MOD;
                continue;
            }   
            dp[i][j]+=(j-(i>s)-(i>t))*dp[i-1][j-1]%MOD+j*dp[i-1][j+1]%MOD;
            dp[i][j]%=MOD;
        }
    }
    cout<<dp[n][1]<<endl;
    return 0;
}

标签:插入,kangaroo,P5999,CEOI2016,leq,MAXN,ll,dp,MOD
From: https://www.cnblogs.com/tanghg/p/18200562/solution-p5999

相关文章

  • 52 Things: Number 35: Give the rough idea of Pollard rho, Pollard "kangaroo" and
    52Things:Number35:GivetheroughideaofPollardrho,Pollard"kangaroo"andparallelPollardrhoattacksonECDLP.52件事:第35件:大致了解Pollardrho、Pollard“袋鼠”和平行的Pollardrho对ECDLP的攻击。 Thisisthelatestinaseriesofblogpoststoadd......
  • P5999 [CEOI2016] kangaroo
    前言写这篇题解的原因是这道题提供了一种新的dp思路——插入dp。题意给定一个长为\(n\)的数轴,一只袋鼠在上面要从\(s\)跳到\(t\),跳跃过程中,每次跳跃方向必须与上一次相反,求方案数。分析拿到这个题其实还是蛮蒙的,但是如果我们转化(抽象)一下题意,就会发现这道题可以看作:......
  • P5999 [CEOI2016] kangaroo 题解
    分析一个妙妙的trick。首先原题可以转化成求有多少\(1\simn\)的排列\(p\)满足\(\foralli\in(1,n)\),\(p_i\)两边的数同时小于或大于\(p_i\),且\(p_1=s,p_n=t\)......
  • P5999 [CEOI2016] kangaroo 蓝 题解
    前言有些题目照常DP不是很好做,感觉像是区间DP,但是怎么设状态都不好转移,那么可以考虑一种维护块儿的DP,就是这道题要用到的知识点。背景分析如果每次跳跃的点的编号形......
  • [CEOI2016] kangaroo题解
    P5999[CEOI2016]kangaroo一类插入式的dp。对于这道题,我们得先做出一个转化,依次考虑每个数插到哪个位置,于是变成了求\(1\)~\(n\)的排列同时满足每个位置上的元素要么......
  • P5999 [CEOI2016] kangaroo 题解
    感觉这样的\(\text{dp}\)题还比较多,思路都比较的神奇。个人感觉比较像区间\(\text{dp}\)的一类变种。但又和区间\(\text{dp}\)的维护方式极不一样。对于此类\(\t......