题目描述
对于一个数列{ai},如果有i<j且ai>aj,那么我们称ai与aj为一对逆序对数。若对于任意一个由1~n自然数组成的数列,可以很容易求出有多少个逆序对数。那么逆序对数为k的这样自然数数列到底有多少个?
输入
第一行为两个整数n,k。
输出
写入一个整数,表示符合条件的数列个数,由于这个数可能很大,你只需输出该数对10000求余数后的结果。
样例输入
4 1
4 1
样例输出
3
样例说明:
下列3个数列逆序对数都为1;分别是1 2 4 3 ;1 3 2 4 ;2 1 3 4;
测试数据范围
30%的数据 n<=12
100%的数据 n<=1000,k<=1000
3
样例说明:
下列3个数列逆序对数都为1;分别是1 2 4 3 ;1 3 2 4 ;2 1 3 4;
测试数据范围
30%的数据 n<=12
100%的数据 n<=1000,k<=1000
/* 设f[i][j]为前i个数,逆序对数为j的方案数 在i-1个数中加入一个数,新增逆序对数为0~i-1,所以f[i][j]=Σf[i-1][k] (j-i+1<=k<=j) 时间复杂度为O(n^3),采用前缀和优化:f[i][j]=g[i-1][j]-g[i-1][j-i] */ #include<cstdio> #include<iostream> #define M 1010 #define Mod 10000 using namespace std; int f[M][M],g[M][M]; int read() { char c=getchar();int flag=1,num=0; while(c<'0'||c>'9'){if(c=='-')flag=-1;c=getchar();} while(c>='0'&&c<='9'){num=num*10+c-'0';c=getchar();} return num*flag; } int main() { int n=read(),k=read(); f[0][0]=1; for(int i=0;i<=k;i++)g[0][i]=1; for(int i=1;i<=n;i++) for(int j=0;j<=k;j++) { f[i][j]=g[i-1][j]; if(j-i>=0)f[i][j]=(f[i][j]+Mod-g[i-1][j-i])%Mod; if(j)g[i][j]=g[i][j-1]; g[i][j]+=f[i][j]; g[i][j]%=Mod; } printf("%d",f[n][k]); return 0; }