[51nod1020]逆序排列

题目链接:

51nod1020

首先考虑设\(f[i][j]\)表示\(i\)个数的排列有\(j\)对逆序对的方案数。

那么怎么求\(f[i][j]\)

若有一个\(1\sim n-1\)的排列,那么现在插入\(n\),那么\(n\)只会和后面的数产生逆序对(前面的一定比\(n\)小),也就可以比原来多产生\(0\sim n-1\)对逆序对。

那么有转移方程:\(f[i][j]=\sum_{k=j-i+1}^j f[i-1][k]\)

前缀和优化,时间复杂度 \(O(nk)\)

辣鸡题目卡空间?

其实只用求一个前缀和数组,回答时用两个相减得答案。

空间复杂度 \(O(nk)\)

代码:

#include <cstdio>

int t,n,k;
int s[1005][20005];
const int p=1000000007;

int main()
{
	for(register int i=1;i<=1000;++i)
		for(register int j=0;j<=20000;++j)
		{
			if(!j)s[i][j]=1;
			else if(j<i)s[i][j]=s[i-1][j]+s[i][j-1];
			else s[i][j]=(s[i-1][j]-s[i-1][j-i]+p)%p+s[i][j-1];
			if(s[i][j]>=p)s[i][j]-=p;
		}
	for(scanf("%d",&t);t--;)
	{
		scanf("%d%d",&n,&k);
		if(!k)printf("%d\n",s[n][k]);
		else printf("%d\n",(s[n][k]-s[n][k-1]+p)%p);
	}
	return 0;
}
posted @ 2019-03-19 19:06  LanrTabe  阅读(196)  评论(0编辑  收藏  举报