[BZOJ4361] isn
[BZOJ4361] isn
Description
给出一个长度为n的序列A(A1,A2...AN)。如果序列A不是非降的,你必须从中删去一个数,这一操作,直到A非降为止。求有多少种不同的操作方案,答案模10^9+7。
Input
第一行一个整数n。接下来一行n个整数,描述A。
Output
一行一个整数,描述答案。
Sample Input
4
1 7 5 3
Sample Output
18
HINT
1<=N<=2000
试题分析
首先这个问题肯定需要整体考虑,所以只能先求出\(g_i\)为长度为i的非将子序列数量。
那么我们来思考去重,发现一种情况合法当且仅当一直存在一个\(a_j<a_i\space (j>i)\),那么如果我们想保留最后的指定序列,一定存在\(a_j<a_{b_i}\space (j>b_i)\)。
那么可以得到一个simple的dp:\(f_{i,j,k}\)表示考虑到\(i\),非降序列最后一个是\(j\),一共有\(k\)个上面的数对的方案数。
但是这样是妥妥的MLE+TLE。。。
考虑单独状态(dp)不行就考虑状态之间的关系(容斥):\(g_i\)不合法一定是从\(g_{i+1}\)删掉一个得到。
所以有:$$ans=\sum g_i(n-i)!-g_{i+1}(n-i-1)!(i+1)$$
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
inline LL read(){
LL 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 LL INF = 2147483600;
const LL MAXN = 3000;
const LL Mod = 1e9+7;
LL N; LL a[MAXN+1],b[MAXN+1];
LL c[2010],s[MAXN+1];
LL f[MAXN+1][MAXN+1];
LL g[MAXN+1],ans;
inline LL lowbit(LL x){return x&(-x);}
inline void Add(LL i,LL k){
for(LL x=i;x<=N;x+=lowbit(x)){
c[x]+=k; if(c[x]>=Mod) c[x]-=Mod;
} return ;
}
inline LL Query(LL i){
LL res=0; if(!i) return 1;
for(LL x=i;x;x-=lowbit(x)){
res+=c[x]; if(res>=Mod) res-=Mod;
}
return res;
}
int main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
N=read(); s[0]=1LL;
for(LL i=1;i<=N;i++) s[i]=s[i-1]*i%Mod;
for(LL i=1;i<=N;i++) b[i]=a[i]=read();
sort(b+1,b+N+1);
for(LL i=1;i<=N;i++) a[i]=lower_bound(b+1,b+N+1,a[i])-b;
for(LL i=1;i<=N;i++) f[1][i]=1;
for(LL i=2;i<=N;i++){
memset(c,0,sizeof(c));
for(LL j=1;j<=N;j++){
f[i][j]+=Query(a[j]);
if(f[i][j]>=Mod) f[i][j]-=Mod;
Add(a[j],f[i-1][j]);
}
}
for(LL i=1;i<=N;i++) for(LL j=1;j<=N;j++) g[i]+=f[i][j],g[i]=(g[i]>=Mod?g[i]-Mod:g[i]);
for(LL i=1;i<=N;i++) ans+=(g[i]*s[N-i]%Mod-g[i+1]*s[N-i-1]%Mod*(i+1)%Mod+Mod)%Mod,ans=(ans>=Mod?ans-Mod:ans);
printf("%lld\n",ans);
return 0;
}
你——悟到了么?