给出一个长度为n的序列A(A1,A2...AN)。如果序列A不是非降的,你必须从中删去一个数,
这一操作,直到A非降为止。求有多少种不同的操作方案,答案模10^9+7。
一行一个整数,描述答案。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; #define N 2005 const ll P=1e9+7; int n,m,A[N],B[N],p[N]; ll fac[N],s[N][N],f[N][N],g[N],ans; inline ll Md(ll a){return a<P?a:a-P;} void Add(int id,int x,ll v){for(;x<=n;x+=x&-x)s[id][x]=Md(s[id][x]+v);} ll Sum(int id,int x){ll re=0; for(;x;x-=x&-x)re=Md(re+s[id][x]); return re;} void prep(){ fac[0]=1; for(ll i=1;i<=n;++i) scanf("%d",&A[i]),B[i]=A[i],fac[i]=fac[i-1]*i%P; sort(B+1,B+n+1); m=unique(B+1,B+n+1)-B-1; for(int i=1;i<=n;++i) p[i]=lower_bound(B+1,B+m+1,A[i])-B;//离散化 } int main(){ scanf("%d",&n); prep(); Add(0,1,1); for(int i=1;i<=n;++i) for(int j=i;j;--j) f[i][j]=Md(f[i][j]+Sum(j-1,p[i])),Add(j,p[i],f[i][j]); for(int i=1;i<=n;++i) for(int j=i;j<=n;++j) g[i]=Md(g[i]+f[j][i]); for(ll i=1;i<=n;++i) ans=Md(Md(ans+g[i]*fac[n-i]%P)-g[i+1]*fac[n-i-1]%P*(i+1)%P+P); printf("%lld",ans); return 0; }
原文:https://www.cnblogs.com/kafuuchino/p/10792793.html