题目描述
将1到n任意排列,然后在排列的每两个数之间根据他们的大小关系插入“>”和“<”。问在所有排列中,有多少个排列恰好有k个“<”。答案对2012取模。
输入输出格式
输入格式:
第一行2个整数n,k。
输出格式:
一个整数表示答案。
输入输出样例
5 2
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; }