【题目描述】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. (1N1000, 0kN).
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 }