zoukankan      html  css  js  c++  java
  • 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
    $f[i][j]$表示前i个数,不下降序列长为j的方案数
    $F[j]=sum_{i=1}^{n}f[i][j]$即不下降序列长为j的总方案数
    但是会有重复,假设在长度为j+1时就已经构成了,那么长度为j的F[j]就会重复计算一部分
    所以长度为i的方案:
    $ans[i]=F[i]*fac[n-i]-F[i+1]*(i+1)*fac[n-i-1]$
    这样DP要$O(n^3)$
    用离散+树状数组(线段树)优化,复杂度$O(n^2logn)$
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 typedef long long lol;
     8 int Mod=1e9+7,n,a[2005],b[2005],m;
     9 int c[2005][2005],fac[2005],tmp,F[2005],ans;
    10 void update(int x,int p,int k)
    11 {
    12   while (x<=n)
    13     {
    14       c[p][x]+=k;
    15       if (c[p][x]>=Mod) c[p][x]-=Mod;
    16       x+=(x&(-x));
    17     }
    18 }
    19 int query(int x,int p)
    20 {
    21   int s=0;
    22   while (x)
    23     {
    24       s+=c[p][x];
    25       if (s>=Mod) s-=Mod;
    26       x-=(x&(-x));
    27     }
    28   return s;
    29 }
    30 int main()
    31 {int i,j;
    32   cin>>n;
    33   fac[0]=1;
    34   for (i=1;i<=n;i++)
    35     fac[i]=1ll*fac[i-1]*i%Mod;
    36   for (i=1;i<=n;i++)
    37     {
    38       scanf("%d",&a[i]);
    39       b[i]=a[i];
    40     }
    41   sort(b+1,b+n+1);
    42   m=unique(b+1,b+n+1)-b-1;
    43   for (i=1;i<=n;i++)
    44     a[i]=lower_bound(b+1,b+m+1,a[i])-b;
    45   for (i=1;i<=n;i++)
    46     {
    47       for (j=i;j>=1;j--)
    48     {
    49       if (j==1) tmp=1;
    50       else tmp=query(a[i],j-1);
    51       update(a[i],j,tmp);
    52       F[j]+=tmp;
    53       if (F[j]>=Mod) F[j]-=Mod;
    54     }
    55     }
    56   for (i=1;i<=n;i++)
    57     {
    58       ans+=1ll*F[i]*fac[n-i]%Mod;
    59       if (ans>=Mod) ans-=Mod;
    60       if (i<n)
    61     ans=(ans-1ll*F[i+1]*fac[n-i-1]%Mod*(i+1)%Mod+Mod)%Mod;
    62     }
    63   cout<<ans;
    64 }
  • 相关阅读:
    cmd 中英文 切换
    comparable和comparator
    ORACLE 毫秒转换为日期 日期转换毫秒
    asp.net弹出对话框
    一、DataBinder.Eval的基本格式
    转载 创业
    常用的js验证数字,电话号码,传真,邮箱,手机号码,邮编,日期
    CodeSmith开发系列资料总结
    SQL函数说明大全
    SQLServer游标的使用
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8505593.html
Copyright © 2011-2022 走看看