P2401 不等数列

题目描述

将1到n任意排列,然后在排列的每两个数之间根据他们的大小关系插入“>”和“<”。问在所有排列中,有多少个排列恰好有k个“<”。答案对2015取模。

注:1~n的排列指的是1~n这n个数各出现且仅出现一次的数列。

输入输出格式

输入格式:

 

第一行2个整数n,k。

 

输出格式:

 

一个整数表示答案。

 

输入输出样例

输入样例#1: 复制
5 2
输出样例#1: 复制
66

说明

对于30%的数据:n <= 10

对于100%的数据:k < n <= 1000

 

//dp[i][j]表示前i个数插入了j个<号的方案数。
//不考虑怎么插入'>'、'<'号,因为符号是根据数字序列确定的, 
//所以我们按顺序插入a->f,符号也就跟着确定了 
//考虑一下这样一个序列:
//            a<b<d>c<e
//    如果在a<b之间插入f,则变成了a<b>f,<号个数不变
//    如果在a之前插入f,则f>a,<号个数也不变
//    即在<号和序列前插入,<号的个数不会改变    
//所以dp[i][j]可以增加dp[i-1][j]*(  j     +    1 )%mod种
//                              <号个数     序列前端 
//    如果在d>c之间插入f,则变成了d<f>c,增加了一个<号
//     如果在e后面插入f,则e<f,增加了一个<号
//    即在>号和序列末插入,<号的个数会增加1 
//所以dp[i][j]可以增加dp[i-1][j-1]*( (i-1)   - (j-1)       -1            +   1       -> i-j  )%mod个
//                                数字个数   <号个数  符号个数为数字个数-1    序列末尾   大于号个数+序列末尾 
//即dp[i][j]=(dp[i-1][j-1]*(i-j)%mod+dp[i-1][j]*(j+1)%mod)%mod;

#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int N=1e3+5; const int mod=2015; int n,k; int dp[N][N]; int main() { scanf("%d%d",&n,&k); dp[1][0]=1; for(int i=2;i<=n;++i) { dp[i][0]=1; //前i个数0个<号的情况只有1种,即单调上升。 for(int j=1;j<=k;++j) { dp[i][j]=(dp[i-1][j-1]*(i-j)%mod+dp[i-1][j]*(j+1)%mod)%mod; } } printf("%d",dp[n][k]); return 0; }

 

posted @ 2018-02-27 10:49  whymhe  阅读(178)  评论(0编辑  收藏  举报