题目描述

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

输入输出格式

输入格式:
第一行为两个整数n,k。

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

输入输出样例

输入样例#1:
4 1

输出样例#1:
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个逆序对的方案数
我们考虑每一次的状态,比如i=4,k=3

1后面加(2,3,4),k=3的方案数
(1和后面的数不能组成逆序对,这就要求(2,3,4)之间组成3对逆序对)

2后面加(1,3,4),k=2的方案数
(2和后面的数能组成1对逆序对,这就要求(1,3,4)之间组成2对逆序对)

3后面加(1,2,4),k=1的方案数
(3和后面的数能组成2对逆序对,这就要求(1,2,4)之间组成1对逆序对)

4后面加(1,2,3),k=0的方案数
(4和后面的数能组成3对逆序对,这就要求(1,2,3)之间组成0对逆序对)

i=5 k=3
1 (2,3,4,5) k=3;
2 (1,3,4,5) k=2;
3 (1,2,4,5) k=1;
4 (1,2,3,5) k=0; 、

这里写代码片
#include<cstdio>
#include<iostream>
#include<cstring>

using namespace std;

const int mod=10000; 
int f[1010][1010];
int n,m;

int main()
{
    scanf("%d%d",&n,&m);
    f[1][0]=1;
    f[2][0]=1; f[2][1]=1;
    f[3][0]=1; f[3][1]=2; f[3][2]=2; f[3][3]=1;
    int i,j,k;
    for (i=4;i<=n;i++)
    {
        f[i][0]=1;
        f[i][1]=i-1;  //可以直接计算 
        for (j=2;j<=m;j++)
            for (k=1;k<=j+1&&k<=i;k++)  //k就是当前填写的数  
            //k<=i保证k在1~i之间,第k个数可以与其他k-1个数组成k-1组逆序对
            //所以前i-1个数只需要组成j-(k-1) 
            //k<=j+1 是为了防止j-k+1为负数 
                f[i][j]=(f[i][j]+f[i-1][j-k+1])%mod;
    }   
    printf("%d",f[n][m]); 
    return 0;
}