bzoj4361: isn【樹狀數組優化dp+容斥】

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

解題思路:

先dp出 f[i] 爲長度爲i的不下降序列數,可以用樹狀數組優化到O(n2logn)

有個直觀的想法就是,枚舉最終序列的長度k,設長度爲k的不下降子序列個數爲 f[k] ,那麼有 (nk)!f[k] 種方案。

但是這樣可能會有一些不合法的方案。

注意到合法方案在最後一步刪之前不是不降序列,所以可以減去在最後一步刪之前是一個長度爲k+1 的不下降子序列轉移來的方案數,即(nk1)!f[k+1](k+1)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll getint()
{
    ll i=0,f=1;char c;
    for(c=getchar();(c!='-')&&(c<'0'||c>'9');c=getchar());
    if(c=='-')c=getchar(),f=-1;
    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
    return i*f;
}
const int N=2005,mod=1e9+7;
inline void add(int &x,int y){x=x+y>=mod?x+y-mod:x+y;}
int n,m,ans,a[N],b[N],f[N],fac[N];
struct BIT
{
    int a[N];
    inline void insert(int i,int v){for(;i<=n;i+=i&-i)add(a[i],v);}
    inline int query(int i){int res=0;for(;i;i-=i&-i)add(res,a[i]);return res;}
}bit[N];
int main()
{
    //freopen("lx.in","r",stdin);
    n=getint();for(int i=1;i<=n;i++)a[i]=b[i]=getint();
    sort(b+1,b+n+1),m=unique(b+1,b+n+1)-b-1;
    for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+m+1,a[i])-b+1;
    fac[0]=1;for(int i=1;i<=n;i++)fac[i]=1ll*fac[i-1]*i%mod;
    bit[0].insert(1,1);
    for(int i=1;i<=n;i++)
        for(int j=n;j;j--)
        {
            int tmp=bit[j-1].query(a[i]);
            add(f[j],tmp),bit[j].insert(a[i],tmp);
        }
    for(int i=1;i<=n;i++)add(ans,(1ll*f[i]*fac[n-i]%mod-1ll*(i+1)*f[i+1]%mod*fac[n-i-1]%mod+mod)%mod);
    cout<<ans<<'\n';
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章