bzoj4361-isn

题意

给出一个数列\(a\),当这个数列不是不下降的时候我们删除其中一个数,直到它是不下降的。

问有多少种删除方案。\(n\le 2000\)

分析

直接算方案数比较难办,转而计算序列数。

如果不考虑不合法的删除(变成不下降之后继续删),那么设长度为\(i\)的不下降子序列有\(g_i\)个,那么得到长度为\(i\)的子序列的方案数为\(g_i(n-i)!\)

现在我们求出所有不管不合法的\(g_i\),那么\(g_i\)中的不合法情况必定是从\(g_{i+1}\)删除一个位置得到的,这是因为\(g_{i+1}\)包含了\(g_i\)的直接不合法情况和间接不合法情况,因为它自己包含了后面的不合法情况。例子\(a=(1,7,3,5)\)可以清楚地说明这一点。

\[ans=\sum g_i(n-i)!-g_{i+1}(n-i-1)!(i+1) \]

\(g_i\)如何求呢?退而求其次,我们算\(f[i][j]\),表示长度为\(i\)\(j\)结尾的子序列数量。

\[\begin{aligned} f[i][j]=\sum f[i-1][k] && k<j,a_k\le a_j \end{aligned} \]

离散化\(a\),用树状数组可以优化到\(O(n^2\log n)\)

这题关键是首先要想到求序列数,接着就是通过减掉不合法情况来计算。

代码

#include<cstdio>
#include<cctype>
#include<cstring>
#include<numeric>
#include<algorithm>
using namespace std;
typedef long long giant;
int read() {
	int x=0,f=1;
	char c=getchar();
	for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
	for (;isdigit(c);c=getchar()) x=x*10+c-'0';
	return x*f;
}
const int maxn=2e3+1;
const int q=1e9+7;
inline int Plus(int x,int y) {return ((giant)x+(giant)y)%q;}
inline int Multi(int x,int y) {return (giant)x*y%q;}
inline int Sub(int x,int y) {return Plus(x,q-y);}
int a[maxn],b[maxn],c[maxn],fac[maxn],n,f[maxn][maxn],g[maxn];
inline int lowbit(int x) {return x&-x;}
inline void inc(int x,int d) {for (;x<=n;x+=lowbit(x)) c[x]=Plus(c[x],d);}
inline int sum(int x) {
	int ret=0;
	for (;x;x-=lowbit(x)) ret=Plus(ret,c[x]);
	return ret;
}
int main() {
#ifndef ONLINE_JUDGE
	freopen("test.in","r",stdin);
#endif
	n=read();
	fac[0]=1;
	for (int i=1;i<=n;++i) fac[i]=Multi(fac[i-1],i);
	for (int i=1;i<=n;++i) a[i]=b[i]=read();
	sort(b+1,b+n+1);
	int m=unique(b+1,b+n+1)-b-1;
	for (int i=1;i<=n;++i) a[i]=lower_bound(b+1,b+m+1,a[i])-b;
	for (int i=1;i<=n;++i) f[1][i]=1;
	for (int i=2;i<=n;++i) {
		memset(c,0,sizeof c);
		for (int j=1;j<=n;++j) {
			f[i][j]=Plus(f[i][j],sum(a[j]));
			inc(a[j],f[i-1][j]);
		}
	}
	for (int i=1;i<=n;++i) for (int j=1;j<=n;++j) g[i]=Plus(g[i],f[i][j]);
	int ans=0;
	for (int i=n;i;--i) ans=Plus(ans,Sub(Multi(g[i],fac[n-i]),Multi(Multi(g[i+1],fac[n-i-1]),i+1)));
	printf("%d\n",ans);
	return 0;
}
posted @ 2017-07-11 16:07  permui  阅读(378)  评论(0编辑  收藏  举报