首页 > 其他分享 >【20联赛集训day10】排列

【20联赛集训day10】排列

时间:2024-09-27 13:45:26浏览次数:9  
标签:排列 20 int rep 1ll day10 集训 dp define

【20联赛集训day10】排列

一个长度为 \(n\) 的排列,每次操作删除所有存在相邻的数字比它更大的数字,问执行 \(k\) 次操作后剩下恰好一个数的排列方案数。

首先因为每次删除至少删一半的数字,所以最多删 \(\log\) 次。

对于一个排列,我们可以发现把序列按最大值劈开,左右两边互不干扰,成为子问题。因此考虑 DP。

可以用笛卡尔树帮助理解,可以想象成在笛卡尔树上 DP。(这里的笛卡尔树是下标满足二叉搜索树性质,权值满足大跟堆,一棵子树一定是一个连续的区间)

\(dp_{i,j,0/1}\) 表示长度为 \(i\) 的序列,删除 \(j\) 次刚好删完,这个序列有没有一边碰到边界,的排列数量。

转移方程详见代码。

可以前缀和优化,时间复杂度 \(O(n^2\log n)\)。

Code

#include<bits/stdc++.h>
// #define DEBUG
#define int ll
#define sf scanf
#define pf printf
#define rep(x,y,z) for(int x=y;x<=z;x++)
using namespace std;
typedef long long ll;
const int N=1005,M=20;
int n;
int p,m;
int ans;
int c[N][N];
int dp[N][M][2],s[N][M][2];
void init(){
    c[0][0]=1;
    rep(i,1,n){
        rep(j,0,i){
            c[i][j]=(j-1>=0?c[i-1][j-1]:0)+c[i-1][j];
            c[i][j]%=p;
        }
    }
}
signed main(){
    #ifdef DEBUG
    freopen("ex_a1.in","r",stdin);
    // freopen("in.txt","r",stdin);
    freopen("my.out","w",stdout);
    #endif
    sf("%lld%lld%lld",&n,&m,&p);
    if(m>18) {
        pf("0\n");
        return 0;
    }
    init();
    dp[0][0][1]=dp[0][0][0]=1;
    rep(i,0,m){
        s[0][i][0]=s[0][i][1]=1;
    }
    rep(i,1,n-1){
        rep(j,1,m){
            rep(k,0,i-1){
                int x=2ll*(1ll*dp[k][j][0]*s[i-k-1][j-1][0]%p)%p+1ll*dp[k][j-1][0]*dp[i-k-1][j-1][0]%p;
                dp[i][j][0]+=1ll*x%p*c[i-1][k]%p;
                dp[i][j][0]%=p;
                int y=1ll*dp[k][j][1]*s[i-k-1][j-1][0]%p+1ll*dp[k][j-1][0]*s[i-k-1][j-1][1]%p;
                dp[i][j][1]+=1ll*y%p*c[i-1][k]%p;
                dp[i][j][1]%=p;
            }
            s[i][j][0]=(s[i][j-1][0]+dp[i][j][0])%p;
            s[i][j][1]=(s[i][j-1][1]+dp[i][j][1])%p;
        }
    }
    rep(k,0,n-1){
        int x=2ll*dp[k][m][1]*s[n-k-1][m-1][1]%p+1ll*dp[k][m][1]*dp[n-k-1][m][1]%p;
        ans+=1ll*x%p*c[n-1][k]%p;
        ans%=p;
    }
    pf("%lld\n",ans);
}

标签:排列,20,int,rep,1ll,day10,集训,dp,define
From: https://www.cnblogs.com/liyixin0514/p/18435541

相关文章

  • P2090 数字对
    P2090数字对不是,这不是黄题吗,鉴定为我太菜了考虑这东西长得像辗转相除法。最终结果一定是\((n,B)\)这样子的。那么它一定是由\((n-B,B)\)转移过来。对于\((a,b)\)如果\(a>b\)它会变成\((a-b,b)\),否则是\((a,b-a)\)。于是也许我们可以枚举\(B\),把\(a-b\)这个操作......
  • P2375 [NOI2014] 动物园
    P2375[NOI2014]动物园题意是对于每个前缀,求前缀后缀不交的且前后缀相等的前后缀数量数组,\(1\lelen\le10^6\)。考虑先求出正常的\(next\)数组,KMP\(O(len)\)求解。对于\(next'\)数组,可以由前一个数的\(next'\)数组转移,如果新数大小超过了\(\frac{i}{2}\)就跳到前......
  • P3195 [HNOI2008] 玩具装箱
    P3195[HNOI2008]玩具装箱\(dp_i\)表示前\(i\)个玩具的最小代价。\(s_i=\sum_{j\lei}c_i+1\)。设\(L'=L+1\)。\(dp_i=\min_{j<i}\{dp_j+(s_i-s_j-L')^2\}\)\(dp_i-s_i'^2+2s_iL'=\min_{j<i}\{dp_j+(s_j'+L)^2-2s_is_j\}\)\(b=y......
  • 自学网络安全(黑客技术)2024年 90天学习计划
    ......
  • 2024年9月27日历史上的今天大事件早读
     1540年09月27日罗马教皇正式批准耶稣会1605年09月27日吉尔霍尔姆战役爆发1825年09月27日世界第一条铁路在英国正式通车1840年09月27日美国海军战略思想家马汉出生1858年09月27日天地会起义,建立大成国1910年09月27日橡胶股灾亡国录1913年09月27日孙中山组建中华革命党......
  • [SWPUCTF 2021 新生赛]easy_md5
    分析一下代码, name不等于password,namd,md5值和password,md5值相等。get传参name,post传参password。$name!=$password&&md5($name)==md5($password)属于MD5绕过中的php==弱类型绕过有两个办法,第一个办法就是importrequests#网站的URLurl="http://node7.a......
  • [GXOI/GZOI2019] 逼死强迫症 题解
    看到\(N\leq2\times10^9\)的范围,一眼矩阵快速幂优化DP。首先考虑朴素DP怎么写。根据题目所给信息,我们设\(dp_{i,0}\)表示前面\(i\)个方砖,并且已经使用了\(2\)个\(1\times1\)的方砖,\(dp_{i,1}\)则表示前面\(i\)个方砖,没有使用任何一个\(1\times1\)的方砖。......
  • [CERC2015] Digit Division 题解
    \(O(n^2)\)做法和大部分人最开始一样,我也想的是DP。设\(dp_i\)表示用前面\(i\)个字符拆分得到的答案。既然是统计方案数,我们肯定是根据前面的答案累加。考虑在\([1,i-1]\)中选择一个\(j\),如果\([j+1,i]\)的字符组成的数字能够被\(m\)整除,那么\(dp_i\)就可以累加......
  • [JLOI2015] 有意义的字符串 题解
    拿到题目,我们首先分析一下这个奇怪的式子:\[\lfloor(\frac{b+\sqrt{d}}{2})^n\rfloor~\text{mod}~p\]重点肯定是在里面的那个式子里面,最显眼的肯定也就是那个\(\sqrt{d}\),根据整体形式,我们可以联系一元二次方程的求根公式\(x=-\dfrac{-b\pm\sqrt{b^2-4ac}}{2a}\),这里也是一......
  • 高性能双核 C66x 定点和浮点 DSP - TMS320C6672ACYPA25 TMS320C6672ACYP TMS320C6672A
    TMS320C6672DSP是一款基于TIKeyStone多核架构的高性能定点/浮点DSP。该器件集成了创新的C66xDSP内核,内核速度最高可达1.5GHz。对于各种应用程序的开发人员来说,例如关键任务系统、医学成像、测试和自动化,以及其他需要高性能的应用程序。这些DSP提供3GHz累积DSP,实现了一个高能......