Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1404 Accepted Submission(s): 709
3 0 3 1
1 4HintThere 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}
从组合角度:
用dp[ n ][ k ]表示 n个数组成的数列 中价值为k的序列数目。
对于数字n分三种情况:
1, 数字n在最后一位(不用考虑它),那么则有序列数目dp[ n-1 ][ k ];
2, 数字n不在最后一位 且当前序列已有价值k ,只需将数字n和序列中k个数(指a[k] > k 的数字)之一交换位置,那么有序列数目dp[n-1][k] * k;
3, 数字n不在最后一位 且当前序列已有价值k-1,我们只需将数字n和序列中n-k个数 (指a[k] <= k 的数字)之一交换位置,那么有序列数目dp[n-1][k-1] * (n-k);
(不要犯晕,这里我们讨论的是数字n的位置,不讨论其他数字的情况,若讨论的话。。。)
(不要问我为什么不讨论 当前序列已有价值k-2或者k-3的情况。。。)
最后得出dp[n][k] = dp[n-1][k] + dp[n-1][k] *k + dp[n-1][k-1] * (n-k)。
便于理解给出一个表格:
行\列 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
1 |
1 |
0 |
- |
- |
- |
- |
- |
2 |
1 |
1 |
0 |
- |
- |
- |
- |
3 |
1 |
4 |
1 |
0 |
- |
- |
- |
4 |
1 |
11 |
11 |
1 |
0 |
- |
- |
5 |
1 |
26 |
66 |
26 |
1 |
0 |
- |
6 |
1 |
57 |
302 |
302 |
57 |
1 |
0 |
为了方便输出,可以先打表:
#include <cstdio> #include <cstring> #define LL long long #define MAX 1000+1 #define MOD 1000000007 using namespace std; LL dp[MAX][MAX]; void getdp() { dp[1][0] = 1;dp[1][1] = 0; for(int i = 2; i < MAX; i++) { dp[i][0] = 1; for(int j = 0; j <= i; j++) { dp[i][j] = (dp[i-1][j]%MOD + (dp[i-1][j]*j)%MOD + (dp[i-1][j-1]*(i-j))%MOD)%MOD; } } } int main() { int n, k; getdp(); while(~scanf("%d%d", &n, &k)) { printf("%lld\n", dp[n][k]); } return 0; }