zoukankan      html  css  js  c++  java
  • BZOJ4361 isn(动态规划+树状数组+容斥原理)

      首先dp出长度为i的不下降子序列个数,显然这可以树状数组做到O(n2logn)。

      考虑最后剩下的序列是什么,如果不管是否合法只是将序列删至只剩i个数,那么方案数显然是f[i]*(n-i)!。如果不合法,说明这个序列是由一个长度为i+1的非降序列删除一个数得来的,所以将其减去f[i+1]*(i+1)*(n-i-1)。这里的斥显然不会有重复。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 2010
    #define P 1000000007
    int n,a[N],b[N],f[N],tree[N][N],ans[N],fac[N],t,tot;
    inline int inc(int &x,int y){x+=y;if (x>=P) x-=P;}
    void add(int x,int k,int p){while (k<=t) inc(tree[x][k],p),k+=k&-k;}
    int query(int x,int k){int s=0;while (k) inc(s,tree[x][k]),k-=k&-k;return s;}
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj4361.in","r",stdin);
        freopen("bzoj4361.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read();
        for (int i=1;i<=n;i++) b[i]=a[i]=read();
        sort(b+1,b+n+1);
        t=unique(b+1,b+n+1)-b-1;
        for (int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+t+1,a[i])-b;
        f[0]=1;add(0,1,1);
        for (int i=1;i<=n;i++)
        {
            for (int j=1;j<=i;j++)
            inc(ans[j],f[j]=query(j-1,a[i]));
            for (int j=1;j<=i;j++)
            add(j,a[i],f[j]);
        }
        fac[0]=1;
        for (int i=1;i<=n;i++) fac[i]=1ll*i*fac[i-1]%P;
        for (int i=1;i<=n;i++)
        inc(tot,(1ll*ans[i]*fac[n-i]%P-1ll*ans[i+1]*fac[n-i-1]%P*(i+1)%P+P)%P);
        cout<<tot;
        return 0;
    }
  • 相关阅读:
    web&http协议&django初识
    jQuery
    BOM&DOM
    装饰器
    JavaScript
    模块
    面向对象编程
    函数
    CSS
    HTML
  • 原文地址:https://www.cnblogs.com/Gloid/p/9864157.html
Copyright © 2011-2022 走看看