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

​传送门​​​
不会做。。orz……

直接推总的方案推一推,可以发现(似乎)是不可优化成O(N^2)的了。。
考虑容斥。
dp1[i][j]表示以i结尾,长度为j的不下降子序列数量,
f[i]表示长度为i的不下降子序列数量。
根据题意,删除到序列为不下降的时候,就应该停止。
也就是说对于长度(x+1),再删除,就是不合法的。
枚举这个x,我们就可以只考虑(x+1)删除一个变成了长度为x,
那么这个不合法的方案数目就是
∑f[x+1]∗(x+1)∗P(n−(x+1))
意义就是对于任意一个长度为(x+1)的子序列,可以删掉任意一个位置,
那么每种子序列都有(x+1)种选择;
而题目要求的是操作序列,每种(x+1)的子序列一定删掉了(n-(x+1))个数,
那么这些数删除的顺序任意,也就是它们的全排列.
也就是∑f[x+1]∗(x+1)∗(n−x−1)!
其中x=0~(n-1)
总的方案数也一样,枚举剩余的子序列长度x,再利用全排列:
∑f[x]∗(n−x)!
其中x=1~n。。

还剩下一个问题就是dp1[i][j]怎么处理出来。
dp1[i][j]=∑dp1[k][j−1],k<i,a[k]<=a[i]
显然是O(N^3)的,不过利用树状数组就可以搞到O(N^2*logN)了。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int
N=2005,
mod=1000000007;
int n,a[N],fac[N],tr[N][N];
int g[N],f[N][N];
struct TMP{int x,id;}tmp[N];
bool cmp(TMP a,TMP b){return a.x<b.x;}
void add(int x,int y,int val){
while (x<=n) tr[y][x]=(tr[y][x]+val)%mod,x+=x&-x;
}
int query(int x,int y){
int val=0;
while (x) val=(val+tr[y][x])%mod,x-=x&-x;
return val;
}
void Pre(){
f[1][1]=1,add(a[1],1,1);
for (int i=2;i<=n;i++){
for (int j=2;j<=i;j++) f[i][j]=query(a[i],j-1);
f[i][1]=1,add(a[i],1,1);
for (int j=2;j<=i;j++) add(a[i],j,f[i][j]);
}
for (int i=1;i<=n;i++){
for (int j=1;j<=i;j++) g[j]=(g[j]+f[i][j])%mod;
}
fac[0]=1;
for (int i=1;i<=n;i++)
fac[i]=(ll)fac[i-1]*i%mod;
}
int count(){
int ans=0;
for (int i=1;i<=n;i++) ans=(ans+(ll)g[i]*fac[n-i]%mod)%mod;
for (int i=2;i<=n;i++)
ans=(ans-(ll)g[i]*i%mod*fac[n-i]%mod+mod)%mod;
return ans;
}
int main(){
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d",&tmp[i].x),tmp[i].id=i;
sort(tmp+1,tmp+1+n,cmp);
int rk=1;a[tmp[1].id]=1;
for (int i=2;i<=n;i++){
rk=rk+(tmp[i].x!=tmp[i-1].x);
a[tmp[i].id]=rk;
}
Pre();
printf("%d\n",count());
return 0;
}