Problem Statement

Find the number of the possible tuples of sequences (A0,A1,…,AN) that satisfy all of the following conditions, modulo M:

  • For every i (0≤iN)Ai is a sequence of length i consisting of integers between 1 and K (inclusive);
  • For every i (1≤iN)Ai−1 is a subsequence of Ai, that is, there exists1≤xii such that the removal of the xi-th element of Ai would result in a sequence equal to Ai−1;
  • For every i (1≤iN)Ai is lexicographically larger than Ai−1.

Constraints

  • 1≤N,K≤300
  • 2≤M≤109
  • NK and M are integers.

Input

Input is given from Standard Input in the following format:

N K M

Output

Print the number of the possible tuples of sequences (A0,A1,…,AN), modulo M.

Sample Input 1

2 2 100

Sample Output 1

5

Five tuples below satisfy the conditions:

  • (),(1),(1,1)
  • (),(1),(1,2)
  • (),(1),(2,1)
  • (),(2),(2,1)
  • (),(2),(2,2)

Sample Input 2

4 3 999999999

Sample Output 2

358

Sample Input 3

150 150 998244353

Sample Output 3

186248260

    最近的一场AGC的题目(1200分题!!),当时比赛的时候一直怼这个题没怼出来QWQ,之后只做了前三个题QWQ(这样也能涨rating???),后来回想了一下,搞了半天才搞出来。
因为这个题目实在是不错,所以我会尽力写好完整的题解的hhhh 第一部分:模型构建。
稍微想想就可以知道,第i行肯定是在第i-1行的基础上再插入一个数字得来的,并且要求字典序更大。
但是稍不留神就会算重,比如 在 1,3,3,2 的两个3后面插入3,得到的新的序列是一样的。
那么在不考虑容斥的情况下,我们如何去构造出 不重复 且满足字典序更大 的计算方案呢? 考虑 a[i][] 和 a[i-1][] 第一个不一样的位置j (为了方便视 a[i-1][i] = 0),显然a[i][j] > a[i-1][j],不然字典序就更小了。
并且很容易想到,如果两个 a[i][] 的 j不一样,那么它们肯定是不同的,所以我们现在就找到了一种不会算重的方案。 我们接着转化模型,设j是最小的满足 a[i][k] != a[i-1][k] 的k,那么我们可以把第i次操作看成 在a[i-1][j] 前面挂了一个新的数 a[i][j] (要求 a[i][j] > a[i-1][j]),从而使a[i-1][j] 位移到了 a[i][j+1]。
于是我们就可以把第i次操作加入的点 抽象成一棵节点带权的有根树的节点(初始只有0节点,且权值是0),一次操作就相当于在某一个节点下挂一个新的权值大于它的节点(对应在原序列某个数前面挂数)。
问题就转化成了,问有多少颗节点数为 n+1 的有根树,儿子的编号都小于爸爸,权值都大于爸爸,并且根的权值是0(对应第一次操作可以加入任意[1,k]的数)。 第二部分:高效求解问题。
不难想到设 f[i][j] 为 有i个节点,且根的权值是j的有根树的方案数,但是转移不是很好想的样子。。。
我们先钦定这棵树内的节点编号是1~i,那么转移就可以写成: f[i][j] = ∑ C(i-2,u-1) * f[u][k] * f[i-u][j] (k>j)
这就相当于枚举,和2节点在一颗子树内的分别是哪些点,这颗子树的方案和剩下的点的方案(依然是以1为根,只不过节点数变成了i-u)。
#include<iostream>
#include<cstdio>
#define ll long long
using namespace std;
const int maxn=305;
int n,k,m,f[maxn][maxn],C[maxn][maxn],g[maxn][maxn];
inline int add(int x,int y){ x+=y; return x>=m?x-m:x;}
inline void ADD(int &x,int y){ x+=y; if(x>=m) x-=m;} inline void solve(){
const int ha=m; C[0][0]=1;
for(int i=1;i<=n;i++){
C[i][0]=1;
for(int j=1;j<=i;j++) C[i][j]=add(C[i-1][j-1],C[i-1][j]);
} fill(g[0],g[0]+k+1,1);
for(int i=0;i<=k;i++) g[1][i]=k-i+1,f[1][i]=1; for(int i=2;i<=n;i++){
// calc f[i][] for(int j=0;j<=k;j++)
for(int u=1;u<i;u++) ADD(f[i][j],C[i-2][u-1]*(ll)g[u][j+1]%ha*(ll)f[i-u][j]%ha); // prepare prefix sum for(int j=k;j>=0;j--) g[i][j]=add(f[i][j],g[i][j+1]);
}
} int main(){
scanf("%d%d%d",&n,&k,&m),n++;
solve(),printf("%d\n",f[n][0]);
return 0;
}

  

 

最新文章

  1. Computop支付网关(一) credit Card
  2. 使用dreamweaver去掉文本中的空格和换行
  3. C++混合编程之idlcpp教程Lua篇(8)
  4. Python正则表达式使用实例
  5. Python基础-day2
  6. zaqar项目介绍
  7. Log4net使用笔记
  8. 李洪强iOS开发之【Objective-C】07-自定义构造方法和description方法
  9. Redis 服务器
  10. Linux中搭建SVN服务器
  11. windows下nginx+tomcat分布式集群部署
  12. Java实现读取文章中重复出现的中文字符串
  13. (转)Spark性能优化:资源调优篇
  14. php 抽象类和接口类
  15. bzoj 4518: [Sdoi2016]征途
  16. I/O-----字符输入流
  17. JAVA作业三
  18. 第5-7次OO作业总结分析
  19. 面向对象。OOP三大特征:封装,继承,多态。 这个讲的是【封存】
  20. C# 生产成条形码3种方法

热门文章

  1. Python代码书写规范
  2. Ubuntu15.04 python升级到python-3.6.x
  3. ASP NET Core ---FluentValidation
  4. hnust 原石法阵
  5. 系统编程--文件IO
  6. java案例1,打印hello java
  7. Struts1 生成Action请求的几种方式分析
  8. hdu 1551 Cable master (二分法)
  9. [HNOI2015][bzoj4009] 接水果 [整体二分+扫描线]
  10. 平面ray trace的数据结构加速