[HAOI2009]逆序对数列

  第一次我无脑敲了个生成排列+归并求逆序对。

  十分。

  然后发现就是很简单的递推。

  因为是1~n的排列。

  每次新加一个数 n+1,且新加的这个数是最大的,假设它放在第 i 位后,新生成的逆序对就是 n-i。

  用 f[i][k] 表示1~i的排列中有k个逆序对的排列数。

  f[i][k] = Σf[i-1][j] ( k-(i-1)<=j<=k ),新加一个数最多新产生 i-1 个逆序对。

  为了不枚举j,可以用前缀和预处理,则复杂度为 O(n*m)。

// q.c

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int M=1000+10;
const int mod=10000;
int n,m,f[M][M],s[M];
int main() {
	freopen("permut.in","r",stdin);
	freopen("permut.out","w",stdout);
	scanf("%d%d",&n,&m);
	f[0][0]=1;
	f[1][0]=1;
	f[1][1]=0;
	for(int i=2;i<=n;i++) {
		s[0]=f[i-1][0];
		for(int j=1;j<=m;j++) s[j]=(f[i-1][j]+s[j-1])%mod;
		for(int j=0;j<=m;j++) 
			if(j-i>=0) f[i][j]=(s[j]-s[j-i]+mod)%mod; // 注意下标,Windows...
			else f[i][j]=s[j]%mod;
	}
	printf("%d\n",f[n][m]);
	return 0;
}

 

posted @ 2018-04-12 08:53  qjs12  阅读(102)  评论(0编辑  收藏  举报