BZOJ 4361 ISN

题面

题目描述

给出一个长度为n的序列A(A1,A2...AN)。如果序列A不是非降的,你必须从中删去一个数,
这一操作,直到A非降为止。求有多少种不同的操作方案,答案模10^9+7。

输入格式

第一行一个整数n。
接下来一行n个整数,描述A。

输出格式

一行一个整数,描述答案。

样例输入

4
1 7 5 3

样例输出

18

数据范围

1<=N<=2000

ai没超long long就对了

关于题意

非降 = 单调不下降

题解

我们考虑一个长度为\(i\)的串, 必定是由一个长度为\(i + 1\)的串去掉一位而来, 并且满足这个长度为\(i + 1\)的串是不合法的.
因此我们令\(g[i]\)表示原串中长度为\(i\)的不下降子序列的数量, 则结束时串的长度为\(i\)的方案数为\(f[i] = g[i] \times (n - i)! - g[i + 1] \times (n - i - 1)! \times (i + 1)\), 用一棵权值树状数组来进行优化, \(O(n^2 \log n)\)即可.

代码:

#include <cstdio>
#include <cctype>
#include <algorithm>
#include <cstring>

namespace Zeonfai
{
    inline int getInt()
    {
        int a = 0, sgn = 1;
        char c;
        while(! isdigit(c = getchar())) if(c == '-') sgn *= -1;
        while(isdigit(c)) a = a * 10 + c - '0', c = getchar();
        return a * sgn;
    }
}
const int MOD = (int)1e9 + 7, N = 2000;
int n;
struct record
{
    int val, pos;
    inline int friend operator <(record a, record b)
    {
        return a.val < b.val;
    }
}rec[N + 1];
struct binaryIndexedTree
{
    int a[N + 1];
    inline void clear()
    {
        memset(a, 0, sizeof(a));
    }
    inline void modify(int pos, int dlt)
    {
        for(int i = pos; i <= n; i += i & - i) a[i] = (a[i] + dlt) % MOD;
    }
    inline int query(int pos)
    {
        int res = 0;
        for(int i = pos; i; i -= i & - i) res = (res + a[i]) % MOD;
        return res;
    }
}BIT;
int main()
{

    #ifndef ONLINE_JUDGE

    freopen("ISN.in", "r", stdin);
    freopen("ISN.out", "w", stdout);

    #endif

    using namespace Zeonfai;
    n = getInt();
    for(int i = 1; i <= n; ++ i) rec[i].val = getInt(), rec[i].pos = i;
    std::sort(rec + 1, rec + n + 1);
    static int a[N + 1];
    int p = 1; a[rec[1].pos] = p;
    for(int i = 2; i <= n; ++ i) a[rec[i].pos] = rec[i].val == rec[i - 1].val ? p : ++ p;
    static int g[N + 1], h[N + 1];
    g[1] = n % MOD; for(int i = 1; i <= n; ++ i) h[i] = 1;
    for(int i = 2; i <= n; ++ i)
    {
        g[i] = 0; BIT.clear();
        for(int j = 1; j <= n; ++ j)
        {
            int tmp = BIT.query(a[j]);
            BIT.modify(a[j], h[j]);
            h[j] = tmp;
            g[i] = (g[i] + h[j]) % MOD;
        }
    }
    static int frac[N + 1]; frac[0] = 1;
    for(int i = 1; i <= n; ++ i) frac[i] = (long long)frac[i - 1] * i % MOD;
    static int f[N + 1];
    for(int i = 1; i <= n; ++ i) f[i] = ((long long)g[i] * frac[n - i] % MOD - (i == n ? 0 : (long long)g[i + 1] * frac[n - i - 1] % MOD * (i + 1) % MOD) + MOD) % MOD;
    int ans = 0;
    for(int i = 1; i <= n; ++ i) ans = (ans + f[i]) % MOD;
    printf("%d\n", ans);
}

posted @ 2017-08-12 22:46  Zeonfai  阅读(157)  评论(0编辑  收藏  举报