[HAOI2009]逆序对数列

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

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

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

Sample Input
4 1

Sample Output
3

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


二维dp

设f[i][j]表示枚举到第i个点,逆序对个数为j的方案数,利用前缀和优化可以将复杂度降到\(O(n^2)\)

/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline char gc(){
	static char buf[1000000],*p1=buf,*p2=buf;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
inline int frd(){
	int x=0,f=1; char ch=gc();
	for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')	f=-1;
	for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<3)+(x<<1)+ch-'0';
	return x*f;
}
inline int read(){
	int x=0,f=1; char ch=getchar();
	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<3)+(x<<1)+ch-'0';
	return x*f;
}
inline void print(int x){
	if (x<0)	putchar('-'),x=-x;
	if (x>9)	print(x/10);
	putchar(x%10+'0');
}
const int N=1e3,p=1e4;
int f[N+10][N+10],g[N+10][N+10];
int main(){
	int n=read(),k=read();
	f[1][0]=1;
	for (int i=0;i<=k;i++)	g[1][i]=1;
	for (int i=2;i<=n;i++){
		for (int j=0;j<=k;j++)
			if (j<i)	f[i][j]=g[i-1][j];
			else	f[i][j]=(g[i-1][j]-g[i-1][j-i]+p)%p;
		g[i][0]=f[i][0];
		for (int j=1;j<=k;j++)	g[i][j]=(g[i][j-1]+f[i][j])%p;
	}
	printf("%d\n",f[n][k]);
}
posted @ 2018-11-22 21:24  Wolfycz  阅读(238)  评论(0编辑  收藏  举报