先用树状数组求出g[i]表示长度为i的不降子序列个数。$O(n^2\log n)$

容斥,最终序列长度为i的方案数为g[i]*(n-i)!,但这里多计算了在删得只剩i个数之前就已经构成不降子序列的情况。

这时考虑最后是从哪个不降子序列删掉一个数的,g[i+1]*(n-i-1)!*(i+1),这里显然不会重复斥掉方案。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 5 typedef long long ll;
 6 using namespace std;
 7 
 8 const int N=2010,mod=1e9+7;
 9 int n,ans,a[N],b[N],fac[N],c[N][N],f[N][N],g[N];
10 void add(int c[],int x,int k){ for (; x<=n; x+=x&-x) c[x]=(c[x]+k)%mod; }
11 int que(int c[],int x){ int res=0; for (; x; x-=x&-x) res=(res+c[x])%mod; return res; }
12 
13 int main(){
14     freopen("bzoj4361.in","r",stdin);
15     freopen("bzoj4361.out","w",stdout);
16     scanf("%d",&n);
17     rep(i,1,n) scanf("%d",&a[i]),b[i]=a[i];
18     sort(b+1,b+n+1);
19     rep(i,1,n) a[i]=lower_bound(b+1,b+n+1,a[i])-b;
20     fac[1]=1; rep(i,2,n) fac[i]=1ll*fac[i-1]*i%mod;
21     add(c[0],1,1);
22     rep(i,1,n) for (int j=i; j; j--)
23         f[i][j]=(f[i][j]+que(c[j-1],a[i]))%mod,add(c[j],a[i],f[i][j]);
24     rep(i,1,n) rep(j,i,n) g[i]=(g[i]+f[j][i])%mod;
25     rep(i,1,n) ans=(ans+((1ll*fac[n-i]*g[i]%mod-1ll*fac[n-i-1]*g[i+1]%mod*(i+1)%mod)%mod+mod)%mod)%mod;
26     printf("%d\n",ans);
27     return 0;
28 }

 

相关文章:

  • 2021-09-08
  • 2021-11-02
  • 2021-08-21
  • 2021-12-03
  • 2021-07-31
  • 2021-09-09
  • 2021-08-03
  • 2021-10-26
猜你喜欢
  • 2021-10-14
  • 2021-07-03
  • 2021-11-15
  • 2021-10-09
  • 2021-10-04
  • 2021-06-29
  • 2022-02-22
相关资源
相似解决方案