【DP】【Asia Harbin 2010/2011】【Permutation Counting】

【题目描述】Given a permutation a1, a2,...aN of {1, 2,..., N}, we define its E-value as the amount of elements where ai > i. For example, the E-value of  permutation {1, 3, 2, 4} is 1, while the E-value of {4, 3, 2, 1} is 2.  You are requested to find how many permutations of {1, 2,..., N} whose E-value  is exactly k.

Input

There are several test cases, and one line for each case, which contains two integers, N and k. (1$ \le$N$ \le$1000, 0$ \le$k$ \le$N).

 

Output

Output one line for each case. For the answer may be quite huge, you need to output the  answer module 1,000,000,007.

Explanation for the sample:

There is only one permutation with E-value 0: {1, 2, 3}, and there are four permutations  with E-value 1: {1, 3, 2}, {2, 1, 3}, {3, 1, 2}, {3, 2, 1}

 

Sample Input

3 0 
3 1

Sample Output

1 
4

【个人体会】一开始在YY能不能找到规律直接能算出答案,然后还打了一个暴力算出了10以内的情况,
后来发现找不出来,于是才回归正道。联想到全错位排列的递推方式,立马懂了这题其实就是个DP。

【题目解析】假设我已经求出了N-1个数,其中ai>i为K个的总方案数。那么考虑添加N这个元素进去
,现在N正好放在第N位上面,那么此时是的排列正好属于DP[N][K],然后将这个元素和之前的ai>i的
元素进行交换,一共是K种交换,得到的方案数都是属于DP[N][K],因此DP[N][K]+=DP[N-1][K]*(K+1),
另外一种是将元素N和ai<=i的元素进行交换,这样的话就会多出1个ai>i的元素(即N这个元素)。因此
DP[N][K]+=DP[N-1][K-1]*(N-1-(K-1))

【代码如下】

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 typedef long long int64;
 6 
 7 const int64 mod = 1000000007;
 8 
 9 int64 F[1001][1001], N, K;
10 
11 int64 Dp(int64 n, int64 k)
12 {
13     if (F[n][k]) return F[n][k];
14     if (n == 0 || n == k) return 0;
15     if (k == 0) return 1;
16     int64 t1 = Dp(n - 1, k) * (k + 1) % mod, t2 = Dp(n - 1, k - 1) * (n - k) % mod;
17     int64 tmp = (t1 + t2) % mod;
18     F[n][k] = tmp;
19     return tmp;
20 }
21 
22 int main()
23 {
24     while (cin >> N >> K) cout << Dp(N, K) << endl;
25     return 0;
26 }



原文地址:https://www.cnblogs.com/GXZC/p/2840498.html