HDU-3664 Permutation Counting(DP)
HDU-3664 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.
InputThere are several test cases, and one line for each case, which contains two integers, N and k. (1 <= N <= 1000, 0 <= k <= N).
OutputOutput one line for each case. For the answer may be quite huge, you need to output the answer module 1,000,000,007.
Sample Input
3 0
3 1
Sample Output
1
4
Hint
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}
题意:问n个数有多少种排列满足ai > i的个数为k个
题解:
DP状态转移方程为dp[i][j]=dp[i-1][j]+dp[i-1][j]*j+dp[i-1][j-1]*(i-j);
dp[i][j]表示的是长度为i的数字串中有j个符合条件的。所以dp[i][j]=长度为i-1的数字串中符合条件的(新来的第i个数字直接连在末尾不改变E值)+长度为i-1的数字串中新来的第i个数字与前面任意一个符合条件的数交换,仍不改变E值,+长度为i-1的数字串中j-1个符合条件的,改变其中任意一个不符合条件的使其符合条件即可满足,而不符合条件的有(i-j)个,所以乘上i-j。
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 #define mod 1000000007
6 using namespace std;
7 typedef long long ll;
8 const int maxn=1010;
9 ll dp[maxn][maxn];
10 ll n,k;
11 int main()
12 {
13 for(ll i=1;i<=1000;i++)
14 {
15 dp[i][0]=1;
16 for(ll j=1;j<i;j++)
17 {
18 dp[i][j]=(dp[i-1][j]+dp[i-1][j]*j+dp[i-1][j-1]*(i-j))%mod;
19 }
20 }
21 while(~scanf("%lld%lld",&n,&k))
22 {
23 printf("%lld\n",dp[n][k]);
24 }
25 return 0;
26 }
错排:让N个数每个数的下标和本身都不一样
原理:f[n]代表的是给你n个数全部错排的种数。f[n]=f[n-1]*(n-1)+f[n-2]*(n-1) f[n-1]表示这n-1个全部为错排,那么第n个和这n-1个任意一个交换都不改变前n个为错排的性质,即f[n-1]*(n-1) f[n-2]表示前这n-1个中有一个位置是正确的,那么正确的位置便有n-1种可能性,将n与这个正确的交换,便是f[n-2]*(n-1).