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).




posted @ 2018-08-28 17:00  *starry*  阅读(120)  评论(0编辑  收藏  举报