题目描述
对于一个数列{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;
}