链接

BZOJ 4361

题面

给出一个长度为n的序列A(A1,A2...AN)。如果序列A不是非降的,你必须从中删去一个数,

这一操作,直到A非降为止。求有多少种不同的操作方案,答案模10^9+7。

N <= 2000。

题解

中国非著名数学老师张军说过:正难则反……

答案就是所有最后剩下一个非降序列的方案 - 不合法的最后剩下一个非降序列的方案。

什么是不合法的、最后剩下一个非降序列的方案呢?就是中间过程中已经形成非降序列的方案。它们的共同特点就是——若最后剩下的序列长度为i,则一定是长度为(i + 1)的另一个非降序列删去(i + 1)个数中的一个数后形成的。要把这部分减去。

设f[i]表示长为i的非降序列的个数。

所以答案就是$$ans = \sum_{i = 1}{n} (f[i] * (n - i) ! - f[i + 1] * (n - i - 1) ! * (i + 1)$$。

问题就是怎么求出f[i]。

设g[i][j]为长为i、最后一位是原序列中第j个数的不降序列数。

则有$$g[i][j] = \sum_{k \le j, a[k] \le a[j]} g[i - 1][k]$$。

求g可以用树状数组优化,总复杂度\(O(n^2 \log n)\)

那么f[i] 就是所有 g[i][j] 之和。

#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
#define enter putchar('\n')
#define space putchar(' ')
template <class T>
void read(T &x){
char c;
bool op = 0;
while(c = getchar(), c > '9' || c < '0')
if(c == '-') op = 1;
x = c - '0';
while(c = getchar(), c >= '0' && c <= '9')
x = x * 10 + c - '0';
if(op) x = -x;
}
template <class T>
void write(T x){
if(x < 0) putchar('-'), x = -x;
if(x >= 10) write(x / 10);
putchar('0' + x % 10);
} const int N = 2005, P = 1000000007;
int n, a[N], g[N][N], f[N], lst[N], idx, sum[N];
ll ans, fac[N]; void add(int p, int x){
while(p <= n) sum[p] = (sum[p] + x) % P, p += p & -p;
}
int ask(int p){
int ret = 0;
while(p) ret = (ret + sum[p]) % P, p -= p & -p;
return ret;
} int main(){ read(n);
for(int i = 1; i <= n; i++)
read(a[i]), lst[i] = a[i];
sort(lst + 1, lst + n + 1);
idx = unique(lst + 1, lst + n + 1) - lst - 1;
for(int i = 1; i <= n; i++)
a[i] = lower_bound(lst + 1, lst + idx + 1, a[i]) - lst;
for(int i = 1; i <= n; i++)
g[1][i] = 1;
for(int i = 2; i <= n; i++){
memset(sum, 0, sizeof(sum));
for(int j = 1; j <= n; j++)
g[i][j] = ask(a[j]), add(a[j], g[i - 1][j]);
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
f[i] = (f[i] + g[i][j]) % P;
fac[0] = 1;
for(int i = 1; i <= n; i++)
fac[i] = fac[i - 1] * i % P;
for(int i = 1; i <= n; i++)
ans = ((ans + f[i] * fac[n - i] % P
- f[i + 1] * fac[n - i - 1] % P * (i + 1) % P) % P + P) % P;
write(ans), enter; return 0;
}

BZOJ 4361 isn | DP 树状数组的更多相关文章

  1. BZOJ.4361.isn(DP 树状数组 容斥)

    题目链接 长度为\(i\)的不降子序列个数是可以DP求的. 用\(f[i][j]\)表示长度为\(i\),结尾元素为\(a_j\)的不降子序列个数.转移为\(f[i][j]=\sum f[i-1][k ...

  2. bzoj 1264 [AHOI2006]基因匹配Match(DP+树状数组)

    1264: [AHOI2006]基因匹配Match Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 793  Solved: 503[Submit][S ...

  3. 树形DP+树状数组 HDU 5877 Weak Pair

    //树形DP+树状数组 HDU 5877 Weak Pair // 思路:用树状数组每次加k/a[i],每个节点ans+=Sum(a[i]) 表示每次加大于等于a[i]的值 // 这道题要离散化 #i ...

  4. 【bzoj2274】[Usaco2011 Feb]Generic Cow Protests dp+树状数组

    题目描述 Farmer John's N (1 <= N <= 100,000) cows are lined up in a row andnumbered 1..N. The cows ...

  5. 奶牛抗议 DP 树状数组

    奶牛抗议 DP 树状数组 USACO的题太猛了 容易想到\(DP\),设\(f[i]\)表示为在第\(i\)位时方案数,转移方程: \[ f[i]=\sum f[j]\;(j< i,sum[i] ...

  6. BZOJ 4361 isn 容斥+dp+树状数组

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4361 题意概述: 给出一个长度为N的序列A(A1,A2...AN).如果序列A不是非降的 ...

  7. BZOJ.4553.[HEOI2016&TJOI2016]序列(DP 树状数组套线段树/二维线段树(MLE) 动态开点)

    题目链接:BZOJ 洛谷 \(O(n^2)\)DP很好写,对于当前的i从之前满足条件的j中选一个最大值,\(dp[i]=d[j]+1\) for(int j=1; j<i; ++j) if(a[ ...

  8. bzoj 3594: [Scoi2014]方伯伯的玉米田 dp树状数组优化

    3594: [Scoi2014]方伯伯的玉米田 Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 314  Solved: 132[Submit][Sta ...

  9. bzoj 1264 [AHOI2006]基因匹配Match dp + 树状数组

    思路:好难想啊, 考虑到应该从每个数字只有5个数字下手, 但是不知道到底该怎么写.. 首先我们将第一个串按数字的种类分类, 每一类里面有5个, 然后将第二个串里面的数字一个一个加,如果一个加入的第 i ...

随机推荐

  1. 20155317 十六周second 取值

    20155317 十六周second 取值 题目如下图: secondset #define base 0xFFFFC0000 # #define &clock void setsecond( ...

  2. mfc CCombox系统定义成员函数

    通过ID操作对象 CComboBox(组合框)控件 CComboBox类常用成员 CComboBox插入数据 CComboBox删除数据 CComboBox运用示例 一.CComboBox控件常用属性 ...

  3. Redis发布订阅和事物笔记

    Redis 发布订阅 Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息. Redis 客户端可以订阅任意数量的频道. 下图展示了频道 cha ...

  4. C#_正则表达式

    概述 正则表达式,主要是用符号描述了一类特定的文本(模式).而正则表达式引擎则负责在给定的字符串中,查找到这一特定的文本. 本文主要是列出常用的正则表达式符号,加以归类说明.本文仅仅是快速理解了正则表 ...

  5. JMeter:生成漂亮的接口/压力测试的HTML报告

    JMeter生成HTML网页报告(非gui模式操作) 我们做性能测试的时候会经常使用一些性能测试工具,比如loardrunner和jmeter,我个人比较喜欢Jmeter这个工具,jmeter之前版本 ...

  6. 当activity改变时,我们如何处理它

    用户和系统触发­的事件,可能造成一个activity状体的改变.这个文档描述了一些常见的情况,和如何去处理这些改变. 原网站:https://developer.android.google.cn/g ...

  7. 初识kibana

    前言: 什么是Kibana?? Kibana是一个开源的分析与可视化平台,设计出来用于和Elasticsearch一起使用的.你可以用kibana搜索.查看.交互存放在Elasticsearch索引里 ...

  8. CSAPP lab2 二进制拆弹 binary bombs phase_3

    给出对应于7个阶段的7篇博客 phase_1  https://www.cnblogs.com/wkfvawl/p/10632044.htmlphase_2  https://www.cnblogs. ...

  9. Actual Time Cost

  10. LINUX基础实验报告

    实验一:主要是介绍Linux系统概况,无运行代码. 实验二:Linux的基本操作 重要知识点 [Tab] 使用Tab键来进行命令补全,Tab键一般键盘是在字母Q旁边,这个技巧给你带来的最大的好处就是当 ...