题面描述
有一个11到nn的排列p1,p2,p3,…,pn,你会对它进行若干轮操作,每一轮操作,你会保留序列中极大的数,也就是说对于每个数字,如果它比相邻的数字都大,那么会被保留下来。比如一个排列(3,2,5,1,4,6),经过一轮操作之后序列变成(3,5,6),第二轮操作之后序列变成(6),经过恰好2轮之后序列里只有一个元素。
请问有多少个长度为n的序列,经过恰好k次操作之后,序列里只有一个元素,由于答案很大,对一个素数P取模。输入格式
第一行三个正整数n,k,P,其中P表示模数,保证P是素数,且108≤P≤109。
输出格式
输出一个数,表示答案。
样例输入
5 3 100000007
样例输出
4
数据规模
对于 10% 的数据,n≤10。
对于 30% 的数据,n≤20。
对于 60% 的数据,n≤100。
对于 100%1 的数据, 1≤k≤n≤103。
同时和位置和数字权值有关的问题。考虑转化到笛卡尔树上
以位置为二叉搜索树的键值,数字为堆的键值建立笛卡尔树
可以发现不考虑边界,记
为一个点被消去的时间
可以得到
边界需要特殊处理
把这个过程换成计数
表示
个点,
轮消去的方案
表示
个点,
轮消去,且当前根在边界上的方案
直接转移即可
#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = j;i <= k;++i)
#define repp(i,j,k) for(int i = j;i >= k;--i)
#define rept(i,x) for(int i = linkk[x];i;i = e[i].n)
#define P pair<int,int>
#define Pil pair<int,ll>
#define Pli pair<ll,int>
#define Pll pair<ll,ll>
#define pb push_back
#define pc putchar
#define mp make_pair
#define file(k) memset(k,0,sizeof(k))
#define ll long long
int rd()
{
int num = 0;char c = getchar();bool flag = true;
while(c < '0'||c > '9') {if(c == '-') flag = false;c = getchar();}
while(c >= '0' && c <= '9') num = num*10+c-48,c = getchar();
if(flag) return num;else return -num;
}
int n,m,p;
int f[1010][13],g[1010][13];
int c[1010][1010];
inline void chmax(int &a,int b){if(a<b)a=b;}
inline int max(int a,int b){return a>b?a:b;}
inline int mul(int a,int b){return 1ll*a*b%p;}
inline int calc(int a,int b){return (a+=b)>=p?a-=p:a;}
int main()
{
n = rd();m = rd();p = rd();
f[0][0] = g[0][0] = 1;
c[0][0] = 1;
rep(i,1,n){c[i][0] = c[i][i] = 1;rep(j,1,i-1) c[i][j] = calc(c[i-1][j-1],c[i-1][j]);}
rep(i,1,n)
rep(j,0,i-1)
{//f[j][].f[k][]->f[i][]
int k = i-j-1;
int t = c[i-1][j];
rep(x,0,m) if(f[j][x]||g[j][x])
rep(y,0,m) if(f[k][y])
f[i][x==y?x+1:max(x,y)] = calc(f[i][x==y?x+1:max(x,y)],mul(f[j][x],mul(f[k][y],t))),
g[i][max(x,y+1)] = calc(g[i][max(x,y+1)],mul( g[j][x] , mul(f[k][y] , t) ));
}
int ans = 0;
rep(i,0,n-1)
{
int j = n-i-1;
rep(x,0,m) rep(y,0,m) if(x == m || y == m)
ans = calc(ans,mul( g[i][x] , mul(g[j][y],c[n-1][i]) ));
}
printf("%d\n",ans);
return 0;
}