• [BZOJ4361] isn


    [BZOJ4361] isn

    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

    试题分析

    首先这个问题肯定需要整体考虑,所以只能先求出(g_i)为长度为i的非将子序列数量。
    那么我们来思考去重,发现一种情况合法当且仅当一直存在一个(a_j<a_ispace (j>i)),那么如果我们想保留最后的指定序列,一定存在(a_j<a_{b_i}space (j>b_i))
    那么可以得到一个simple的dp:(f_{i,j,k})表示考虑到(i),非降序列最后一个是(j),一共有(k)个上面的数对的方案数。
    但是这样是妥妥的MLE+TLE。。。
    考虑单独状态(dp)不行就考虑状态之间的关系(容斥):(g_i)不合法一定是从(g_{i+1})删掉一个得到。
    所以有:$$ans=sum g_i(n-i)!-g_{i+1}(n-i-1)!(i+1)$$

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
     
    using namespace std;
    #define LL long long
     
    inline LL read(){
        LL x=0,f=1; char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const LL INF = 2147483600;
    const LL MAXN = 3000;
    const LL Mod = 1e9+7;
     
    LL N; LL a[MAXN+1],b[MAXN+1];
    LL c[2010],s[MAXN+1];
    LL f[MAXN+1][MAXN+1];
    LL g[MAXN+1],ans;
     
    inline LL lowbit(LL x){return x&(-x);}
    inline void Add(LL i,LL k){
        for(LL x=i;x<=N;x+=lowbit(x)){
                c[x]+=k; if(c[x]>=Mod) c[x]-=Mod;
        } return ;
    }
    inline LL Query(LL i){
        LL res=0; if(!i) return 1;
        for(LL x=i;x;x-=lowbit(x)){
                res+=c[x]; if(res>=Mod) res-=Mod;
        }
        return res;
    }
     
    int main(){
        //freopen(".in","r",stdin);
        //freopen(".out","w",stdout);
        N=read(); s[0]=1LL;
        for(LL i=1;i<=N;i++) s[i]=s[i-1]*i%Mod;
        for(LL i=1;i<=N;i++) b[i]=a[i]=read();
        sort(b+1,b+N+1);
        for(LL i=1;i<=N;i++) a[i]=lower_bound(b+1,b+N+1,a[i])-b;
        for(LL i=1;i<=N;i++) f[1][i]=1;
        for(LL i=2;i<=N;i++){
            memset(c,0,sizeof(c));
            for(LL j=1;j<=N;j++){
                f[i][j]+=Query(a[j]);
                if(f[i][j]>=Mod) f[i][j]-=Mod;
                Add(a[j],f[i-1][j]);
            }
        }
        for(LL i=1;i<=N;i++) for(LL j=1;j<=N;j++) g[i]+=f[i][j],g[i]=(g[i]>=Mod?g[i]-Mod:g[i]);
        for(LL i=1;i<=N;i++) ans+=(g[i]*s[N-i]%Mod-g[i+1]*s[N-i-1]%Mod*(i+1)%Mod+Mod)%Mod,ans=(ans>=Mod?ans-Mod:ans);
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    让你少奋斗10年的工作经验
    POJ Exponentiation解题
    数据结构树和二叉树
    语句摘录
    ACM解题报告格式
    编程规范
    数据结构图
    Java学习之二Java反射机制
    使用Python正则表达式提取搜索结果中的站点
    toj 1702 A Knight's Journey
  • 原文地址:https://www.cnblogs.com/wxjor/p/9532236.html
Copyright © 2020-2023  润新知