首页 > 其他 > 详细

51nod 1020 逆序排列

时间:2017-09-30 22:38:12      阅读:301      评论:0      收藏:0      [点我收藏+]

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1020

题意:
技术分享

 

思路:

一开始用了三重循环。。。

设f(n,k)表示n个数的排列中逆序数个数为k的排列数。

最大的数n可能会排在第n-i位,从而产生i个与n有关的逆序对,去掉n之后,剩下的n-1个数的排列有k-i个逆序对。所以,f(n,k)=求和(f(n-1,k-i))(0<=i<n)。
同理有f(n,k-1)=求和(f(n-1,k-1-i))(0<=i<n)。
两式相减,可得f(n,k)-f(n,k-1)=f(n-1,k)-f(n-1,k-n)。
递推公式为f(n,k)=f(n,k-1)+f(n-1,k)-f(n-1,k-n)。
 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<vector>
 6 #include<stack>
 7 #include<queue>
 8 #include<cmath>
 9 #include<map>
10 #include<set>
11 using namespace std;
12 typedef long long ll;
13 typedef pair<int,int> pll;
14 const int INF = 0x3f3f3f3f;
15 const int maxn=1000+5;
16 const int mod = 1e9+7;
17 
18 int n, k;
19 int dp[maxn][20005];
20 
21 void init()
22 {
23     for (int i = 1; i <= 1000; ++i)
24         dp[i][0] = 1;
25     for (int i = 2; i <= 1000; ++i)
26     {
27         for (int j = 1; j <= i * (i - 1) / 2 && j <= 20000; ++j)
28         {
29             dp[i][j] = (dp[i][j - 1] + dp[i - 1][j]) % mod;
30             if (j - i >= 0)
31                 dp[i][j] -= dp[i - 1][j - i];
32             dp[i][j] = (dp[i][j] + mod) % mod;
33         }
34     }
35 }
36 
37 int main()
38 {
39     //freopen("in.txt","r",stdin);
40     int T;
41     init();
42     scanf("%d", &T);
43     while (T--)
44     {
45         scanf("%d%d", &n, &k);
46         printf("%d\n", dp[n][k]);
47     }
48 
49 }

 

51nod 1020 逆序排列

原文:http://www.cnblogs.com/zyb993963526/p/7616228.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!