序列
monyhzc (感谢他让我明白了)
————————————————————————————————————
我们先观察,发现每次只会从上一个序列多增一个数,其实就是说是将原序列复制一遍,并在适当位置添上一个数,还要保证添上的数大于后面的一个数,其实我们可以认为是将原序列中的一个数前面长出一个比它大的数
因为最后一个位置不好算长出来,所以我们可以在序列末尾补一个0,这样我们就可以表示最后一个位置长出来了
—————————————————————————————————————
(这个dp思路太难想了)
dp[i][j]表示长度为i的序列最大值不大于j的方案数,pre[i][j]表示dp[i][1-j]的前缀和
(其实就是两个前缀)
考
虑
如
何
转
移
d
p
[
i
]
[
j
]
考虑如何转移dp[i][j]
考虑如何转移dp[i][j]
我
们
先
枚
举
一
个
x
,
保
证
x
前
的
数
是
由
x
长
出
来
的
,
即
后
面
的
方
案
数
为
p
r
e
[
i
−
l
]
[
x
−
1
]
,
即
后
面
的
最
大
值
不
超
过
x
,
前
面
的
可
以
随
便
选
数
,
为
d
p
[
i
−
l
]
[
x
]
因
为
相
当
于
我
们
已
经
有
一
个
x
,
0
,
的
序
列
,
长
度
为
2
,
我
们
可
以
在
0
前
面
和
x
前
面
选
数
,
即
已
经
有
2
个
时
间
填
了
数
,
所
以
总
共
有
i
−
2
个
时
间
可
以
加
入
值
,
然
后
x
前
需
要
加
入
l
−
1
个
值
,
即
需
选
择
l
−
1
个
时
间
加
入
值
,
所
以
,
所
以
组
合
系
数
为
C
i
−
2
l
−
1
,
我们先枚举一个x,保证x前的数是由x长出来的,即后面的方案数为pre[i-l][x-1],即后面的最大值不超过x,前面的可以随便选数,为dp[i-l][x]因为相当于我们已经有一个 x,0,的序列,长度为2,我们可以在0前面和x前面选数,即已经有2个时间填了数,所以总共有i-2个时间可以加入值,然后x前需要加入l-1个值,即需选择l-1个时间加入值,所以,所以组合系数为C_{i-2}^{l-1},
我们先枚举一个x,保证x前的数是由x长出来的,即后面的方案数为pre[i−l][x−1],即后面的最大值不超过x,前面的可以随便选数,为dp[i−l][x]因为相当于我们已经有一个x,0,的序列,长度为2,我们可以在0前面和x前面选数,即已经有2个时间填了数,所以总共有i−2个时间可以加入值,然后x前需要加入l−1个值,即需选择l−1个时间加入值,所以,所以组合系数为Ci−2l−1,
所以dp[i][j]=(dp[i][j]+dp[i-l][j]*pre[l][j-1]*C(i-2,l-1))
—————————————————————————————————————
初
始
状
态
:
将
d
p
[
1
]
[
0
,
1
,
.
.
.
.
,
k
]
都
赋
值
为
1
,
这
样
就
能
保
证
后
面
的
最
大
值
可
以
为
任
意
数
都
可
以
转
移
初始状态:将dp[1][0,1,....,k]都赋值为1,这样就能保证后面的最大值可以为任意数都可以转移
初始状态:将dp[1][0,1,....,k]都赋值为1,这样就能保证后面的最大值可以为任意数都可以转移
—————————————————————————————————————
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;//有乘法,所以要开longlong
const int N=305;
ll n,k,mod,c[N][N],pre[N][N],dp[N][N];
int main(){
scanf("%lld%lld%lld",&n,&k,&mod);
c[1][0]=c[1][1]=1%mod;c[0][0]=1%mod;
for(int i=2;i<=n;i++){
c[i][i]=1%mod;c[i][0]=1%mod;
for(int j=1;j<i;j++)
{
c[i][j]=1ll*(c[i-1][j-1]+c[i-1][j])%mod;
}
}
dp[1][0]=1%mod;pre[1][0]=1%mod;
for(int i=1;i<=k;i++){dp[1][i]=1%mod;pre[1][i]=(pre[1][i-1]+dp[1][i])%mod;}
for(int i=2;i<=n+1;i++)
for(int j=1;j<=k;j++){
for(int len=1;len<i;len++){
dp[i][j]=1ll*(dp[i][j]+(((dp[i-len][j])*c[i-2][len-1]%mod)*(pre[len][j-1])%mod)%mod)%mod;
pre[i][j]=1ll*((pre[i][j-1]+dp[i][j])%mod)%mod;
}
}
printf("%lld",dp[n+1][k]);
}