题目描述

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

输入输出格式

输入格式:

 

第一行2个整数n,k。

 

输出格式:

 

一个整数表示答案。

 

输入输出样例

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

说明

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

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

分析:求方案数,想不到数学方法,用dp来做,看数据范围,应该是一个O(nk)的算法,那么设f[i][j]表示前i个数中插入了j个'<'号的方案数,考虑第i个数的插入,这个数比前i-1个数都要大,它插入进来后可能会多一个'<'号也可能不会多.如果多了一个'<'号,那么就有i-j个位置可以插入,可以插在队尾和i-j - 1个大于号的位置,如果没有多'<'号,那么我们在'<'号的位置插入或者在队首插入,这样可以得到式子f[i][j] = f[i-1][j] * (j + 1) + f[i-1][j-1] * (i - j).

#include <cstdio>
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>

using namespace std;

const int mod = 2012;

int n, k, f[1010][1010];

int main()
{
    scanf("%d%d", &n, &k);
    f[0][0] = 1;
    for (int i = 1; i <= n; i++)
    {
        f[i][0] = 1;
        for (int j = 1; j <= k; j++)
            f[i][j] = (f[i - 1][j] * (j + 1) + f[i - 1][j - 1] * (i - j)) % mod;
    }
    printf("%d\n", f[n][k]);

    return 0;
}