http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1968
题意:
对于任一种N的排列A,定义它的E值为序列中满足A[i]>A[i+1]的数的个数。给定N和K(K<=N<=1000),问N的排列中E值为K的个数。
思路:
这道题目和杭电的3664非常像。
d【i】【j】表示分析到i这个数时的E值为j的个数。
那么如何计算出d【i】【j】呢?得根据d【i-1】【j】和d【i-1】【j-1】递推出来。
①首先考虑d【i-1】【j】(此时不改变E值):
1)、因为此时i是最大的,所以插在最后不改变E值,方法数为1
2)、插入到每对逆序数中间,这样逆序数数量不会改变,方法数为j(因为一共有j对逆序对)
②然后是d【i-1】【j】(此时要让E值+1)
1)、插入到最前面,E值+1,方法数为1
2)、插入到不是逆序对中去,构成逆序对,E值+1,(i-1的数中一共有i-2对数,现在存在j-1对逆序对,那么i-2-j+1对数不是逆序对,可以插入到这几对数当中去),方法数为i-j+1
所以,最后的递推式就是
dp[i][j] = dp[i-1][j-1]*(i-j) + dp[i-1][j]*(j+1);
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<sstream> 6 #include<vector> 7 #include<stack> 8 #include<queue> 9 #include<cmath> 10 #include<map> 11 #include<set> 12 using namespace std; 13 typedef long long ll; 14 typedef pair<int,int> pll; 15 const int INF = 0x3f3f3f3f; 16 const int maxn = 100 + 5; 17 18 const int mod=1001113; 19 20 int dp[200][200]; 21 22 void init() 23 { 24 for(int i=0;i<=100;i++) dp[i][0]=1; 25 for(int i=2;i<=100;i++) 26 { 27 for(int j=1;j<i;j++){ 28 dp[i][j]=(dp[i-1][j-1]*(i-j)+dp[i-1][j]*(j+1))%mod; 29 } 30 } 31 } 32 33 int main() 34 { 35 int T; 36 int t,n,k; 37 init(); 38 //freopen("in.txt","r",stdin); 39 scanf("%d",&T); 40 while(T--) 41 { 42 scanf("%d%d%d",&t,&n,&k); 43 printf("%d %d ",t,dp[n][k]); 44 45 } 46 return 0; 47 }