bzoj 4361 isn - 容斥 - dp

考虑枚举最后剩下的序列的长度,过程随便删,这样的问题是,例如剩下的长度是x,但你删除到x+1的时候就已经不能删了。维护这个恰好很难,但是可以容斥,因为不合法的情况一定是之前也是个非降序列。


#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#define lint long long
#define mod 1000000007
#define clr(c) memset(c,0,sizeof(c))
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define N 2010
#define lb(x) ((x)&(-(x)))
using namespace std;
int n,c[N],f[N][N],g[N],ans,fac[N];lint a[N];vector<lint> v;
inline int mol(lint x) { return x%=mod,(x<0?x+mod:x); }
inline int update(int p,int v) { for(;p<=n;p+=lb(p)) (c[p]+=v)%=mod;return 0; }
inline int query(int p,int v=0) { for(;p;p-=lb(p)) (v+=c[p])%=mod;return v; }
int main()
{
    scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%lld",&a[i]),v.push_back(a[i]);
    sort(v.begin(),v.end()),v.erase(unique(v.begin(),v.end()),v.end()),update(1,1);
    for(int i=1;i<=n;i++) a[i]=lower_bound(v.begin(),v.end(),a[i])-v.begin()+1;
    for(int i=1;i<=n;i++,clr(c)) rep(j,1,n) f[i][j]=query(a[j]),update(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;
    rep(i,fac[0]=1,n) fac[i]=(lint)fac[i-1]*i%mod;
    for(int i=1;i<=n;i++)
        ans=mol(ans+(lint)fac[n-i]*g[i]-(i<n?(i+1ll)*g[i+1]%mod*fac[n-i-1]:0));
    return !printf("%d\n",ans);
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/81359964