题面在这里
\(f_{i,j}\):长度为i,以j结尾的非降序列个数 \[
f_{i,j}=\sum_{k\lt i}^{a_k\le a_i} f_{i-1,k}
\] 直接用树状数组优化到\(O(n^2\log n)\)
于是得到\(g_i\):长度为i的非降序列个数
答案就是 \[
\sum_{i=1}^n g_i(n-i)!-g_{i+1}(i+1)(n-i-1)!
\] 如何理解?
直接\(\sum g_i(n-i)!\)肯定是不对的,因为有些已经变成非降序列但没有停止删除
但是不合法方案一定是由\(g_{i+1}\)来的,枚举删去哪个数,得到对应方案
示例程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| #include<cstdio> #include<cstring> #include<algorithm> #define cl(x,y) memset(x,y,sizeof(x)) using namespace std; typedef long long ll;
const int maxn=2005,MOD=1e9+7; int n,m,a[maxn],b[maxn],f[maxn][maxn],g[maxn]; ll fac[maxn]; int BIT[maxn]; #define lowbit(x) ((x)&-(x)) inline void ist(int x,int w){ for (int i=x;i<=m;i+=lowbit(i)) (BIT[i]+=w)%=MOD; } inline int qry(int x){ int res=0; for (int i=x;i;i-=lowbit(i)) (res+=BIT[i])%=MOD; return res; } int main(){ scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i]; sort(b+1,b+1+n); m=unique(b+1,b+1+n)-1-b; for (int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+1+m,a[i])-b; for (int i=1;i<=n;i++) f[1][i]=1; for (int i=2;i<=n;i++){ cl(BIT,0); for (int j=1;j<=n;j++){ f[i][j]=qry(a[j]); ist(a[j],f[i-1][j]); } } for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) (g[i]+=f[i][j])%=MOD; fac[0]=1; for (int i=1;i<=n;i++) fac[i]=(fac[i-1]*i)%MOD; ll ans=0; for (int i=1;i<=n;i++) (ans+=g[i]*fac[n-i]%MOD-g[i+1]*fac[n-i-1]%MOD*(i+1)%MOD)%=MOD; printf("%lld",(ans+MOD)%MOD); return 0; }
|