BZOJ4361: isn

BZOJ4361: isn

https://www.lydsy.com/JudgeOnline/problem.php?id=4361

Sol.

最终的状态一定是一个不降子序列。

令f[i][j]表示长度为i,最后一个数为a[j]不降子序列个数。

那么有f[i][j]=f[i-1][k](k<=j&&a[k]<=a[j]) 树状数组优化转移。

考虑g[i]= $ \sum $ f[i][1..n]

$ g[i] \times (n-i)! $ 就是i的答案。

然而这样会重,有可能还没删完就不降了

方案数要减去g[i+1]*(i+1)  相当于g[i+1]乘上枚举最后删的点:i+1种

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#define maxn 2005
#define mod 1000000007
#define ll long long
using namespace std;
int n,a[maxn],A[maxn],cnt;
ll h[maxn],f[maxn][maxn],g[maxn],tr[maxn];
map<int,int>ls;
ll ask(int x){
    ll sum=0;for(int i=x;i;i-=i&-i)(sum+=tr[i])%=mod;return sum;
}
void add(int x,ll v){
    for(int i=x;i<=cnt;i+=i&-i)(tr[i]+=v)%=mod;
}
void lsh(){
    sort(A+1,A+n+1);
    for(int i=1;i<=n;i++)if(!ls[A[i]])ls[A[i]]=++cnt;
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++)scanf("%d",&a[i]),A[i]=a[i];
    lsh();
    for(int i=1;i<=n;i++)a[i]=ls[a[i]];
    h[0]=1;for(int i=1;i<=n;i++)h[i]=1LL*h[i-1]*i%mod;
    for(int i=1;i<=n;i++)f[1][i]=1;
    for(int j=2;j<=n;j++){
        for(int i=1;i<=n;i++){
            (f[j][i]+=ask(a[i]))%=mod;
            add(a[i],f[j-1][i]);
        }
        for(int i=1;i<=cnt;i++)tr[i]=0;
    }
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)g[i]=(g[i]+f[i][j])%mod;
    ll ans=0;
    for(int i=1;i<=n;i++)g[i]=g[i]*h[n-i]%mod;
    for(int i=1;i<=n;i++)ans=(ans+g[i]-g[i+1]*(i+1))%mod;
    ans=(ans%mod+mod)%mod;
    cout<<ans<<endl;
    return 0;
}

 

posted @ 2019-11-07 11:45  liankewei123456  阅读(161)  评论(0编辑  收藏  举报