BZOJ2431 [HAOI2009]逆序对数列

Description

对于一个数列{ai},如果有i<j且ai>aj,那么我们称ai与aj为一对逆序对数。若对于任意一个由1~n自然数组成的数列,可以很容易求出有多少个逆序对数。那么逆序对数为k的这样自然数数列到底有多少个?

Input

 第一行为两个整数n,k。

Output

写入一个整数,表示符合条件的数列个数,由于这个数可能很大,你只需输出该数对10000求余数后的结果。

 


Sample Input

样例输入

4 1


Sample Output

样例输出

3

样例说明:

下列3个数列逆序对数都为1;分别是1 2 4 3 ;1 3 2 4 ;2 1 3 4;



测试数据范围

30%的数据 n<=12

100%的数据 n<=1000,k<=1000

 

 
 
正解:DP(递推)
解题报告:
  这道题我居然没能一眼秒。。。
  令f[i][j]表示前i个数逆序对数为j的序列个数,考虑DP(递推)。因为插入前i-1个数的时候方案已经得出了,我们需要插入第i个数获得新的一些序列。
  因为i比前面任何一个数都要大,所以插在第几位,就会比后面的数大,对于总逆序对产生贡献。考虑贡献大小,可以插在前i-1个数的最后面,那么对于逆序对数没有产生任何贡献,所以就是从f[i-1][j]转移过来,但是插在其他位置呢?如果插在i-2个数后面就是产生1的贡献,所以是f[i-1][j-1]。。。最后i-1中总共i-1个数,所以新产生的贡献最大为i-1。可以得到方程式:f[i][j]=∑f[i-1][j-k](0<=k<i)
  复杂度O(N^3)但是可以优化。因为每次用的是一段,所以前缀和优化一下,没必要每次重新统计。
 
 1 //It is made by jump~
 2 #include <iostream>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cstdio>
 6 #include <cmath>
 7 #include <algorithm>
 8 #include <ctime>
 9 #include <vector>
10 #include <queue>
11 #include <map>
12 #include <set>
13 #ifdef WIN32   
14 #define OT "%I64d"
15 #else
16 #define OT "%lld"
17 #endif
18 using namespace std;
19 typedef long long LL;
20 const int MAXN = 1011;
21 const int MOD = 10000;
22 int n,k;
23 int f[MAXN][MAXN];//f[i][j]表示前i个数逆序对为j个的序列数
24 
25 inline int getint()
26 {
27        int w=0,q=0;
28        char c=getchar();
29        while((c<'0' || c>'9') && c!='-') c=getchar();
30        if (c=='-')  q=1, c=getchar();
31        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
32        return q ? -w : w;
33 }
34 
35 inline void work(){
36     n=getint(); k=getint();
37     f[0][0]=1; for(int i=1;i<=n;i++) f[i][0]=1;
38     int now=0;
39     for(int i=1;i<=n;i++) {//新加入的i可以插在之前的i-1个数中的任意位置,就会产生对逆序对数不同的贡献,可能贡献为0但最多为i-1。所以能加入当前的范围为j-i+1到j
40     now=f[i-1][0];
41     for(int j=1;j<=k;j++){
42         if(j-i>=0)  now-=f[i-1][j-i];
43         now+=f[i-1][j];
44         f[i][j]+=now;
45         f[i][j]+=MOD; if(f[i][j]>=MOD) f[i][j]%=MOD;
46     }
47     }
48     printf("%d",f[n][k]);
49 }
50 
51 int main()
52 {
53   work();
54   return 0;
55 }
 
原文地址:https://www.cnblogs.com/ljh2000-jump/p/5803808.html