zoukankan      html  css  js  c++  java
  • ZR#1015

    ZR#1015

    解法:

    我们需要求得, $ g_i $ 表示长度为的最长不下降子序列个数。
    设 $ f_{i,j} $ 表示统计第前$ i $ 个数字,得到最长不下降子序列末端为 $ j $ 。
    显然这个状态可以从前面所有转移过来。
    树状数组优化一下。
    考虑到在 $ g_i $ 状态下,我们可以以任意顺序删去个 $ n-i $ 数,则长度为 $ i $ 的最长不下降子序列方案数为 $ g_i(n - i) !$
    但是,不能保证它在成为最长不下降子序列时就停止删数。
    不合法方案数为 $ g_{i+1}
    (n- i - 1)! * (i + 1) $ (最后一次可以删个数中任意一个)。
    所以统计答案的时候就是 $ ans = g_i * (n - i)! - g_{i+1}*(n-i-1)! * (i + 1) $

    CODE:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    
    using namespace std;
    
    #define LL long long
    #define N 2010
    const int mod = 1e9 + 7;
    
    int n,pos[N];
    LL a[N],t[N],sum[N][N];
    LL f[N][N],g[N],fac[N],ans;
    
    inline int lowbit(int x) {
        return x & -x;
    }
    void update(int id,int x,LL v) {
        for(int i = x ; i <= n ; i += lowbit(i))
            sum[id][i] = (sum[id][i] + v) % mod;
    }
    LL query(int id,int x) {
        LL ans = 0;
        for(int i = x ; i ; i -= lowbit(i))
            ans = (ans + sum[id][i]) % mod;
        return ans;
    }
    
    int main() {
        scanf("%d",&n);
        for(int i = 1 ; i <= n ; i++)
            scanf("%lld",&a[i]);
        for(int i = 1 ; i <= n ; i++) t[i] = a[i];
        sort(t + 1,t + n + 1);
        int num = unique(t + 1,t + n + 1) - t - 1;
        fac[1] = 1;
        for(int i = 1 ; i <= n ; i++) 
            pos[i] = lower_bound(t + 1,t + num + 1,a[i]) - t;
        for(int i = 2 ; i <= n ; i++)
            fac[i] = 1LL * fac[i - 1] * i % mod;
        update(0,1,1);
        for(int i = 1 ; i <= n ; i++) {
            for(int j = i ; j >= 1 ; j--) {
                f[i][j] = (f[i][j] + query(j - 1,pos[i]) % mod) % mod;
                update(j,pos[i],f[i][j] % mod);
            }
        }
        for(int i = 1 ; i <= n ; i++) {
            for(int j = 1 ; j <= n ; j++) {
                g[i] = (g[i] + f[j][i]) % mod;
            }
        }
        for(int i = 1 ; i <= n ; i++)
            ans = ((ans % mod + (fac[n - i] % mod * g[i] % mod) % mod) % mod - fac[n - i - 1] % mod * g[i + 1] % mod * (i + 1) % mod + mod) % mod;
        printf("%lld
    ",ans);
        //system("pause");
        return 0;
    }
    
  • 相关阅读:
    SysTick—系统定时器
    FreeRtos——单任务
    binutils工具集之---objdump
    对连接器的思考
    数组和指针并不相同
    typedef可以成为你的朋友
    gcc,一个神奇的编译器
    FreeRtos——移植
    Makefile 13——理解make的解析行为
    Makefile 12——改善编译效率
  • 原文地址:https://www.cnblogs.com/Repulser/p/11708979.html
Copyright © 2011-2022 走看看