题目描述
对于一个数列{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[i][j]表示填到 i ,之前有 j 个逆序对的方案数
- 因为i比之前的数都到,不同的插入可以产生0~ i-1个逆序对。
所以dp[i][j]+=dp[i-1][k] (j-i+1<=k<=j) - 用前缀和优化dp[i-1][k]=sum[j]-sum[ max(j-i,0) ]
// brief
const int mod=10000;
int f[1100][1100];
int main()
{
int n,m;
cin>>n>>m;
f[1][0]=1;
for(int i=2;i<=n;i++)// 填到i位
{
for(int j=0;j<=m;j++)// j个逆序对
{
for(int k=0;k<i;k++)// 枚举i填在哪里
{
f[i][j]=(f[i][j]+f[i-1][j-k])%mod;
}
}
}
cout<<f[n][m]<<endl;
return 0;
}
using namespace std;
const int mod=10000;
int f[1100][1100];
int main()
{
int n,k;
cin>>n>>k;
f[1][0]=1;
for(int i=2;i<=n;i++)// 填到i位
{
int sum=0;
for(int j=0;j<=k;j++)// j个逆序对
{
sum=(sum+f[i-1][j])%mod;
f[i][j]=sum;
if(j-i+1>=0) sum=(sum-f[i-1][j-i+1]+mod)%mod;
}
}
cout<<f[n][k]<<endl;
return 0;
}