前言

数学符号约定:

\(\dbinom{n}{m}\):表示 \(n\) 选 \(m\) 。

如非特殊说明,将会按照上述约定书写符号。

题目分析:

考虑题目的问题弱一点的版本,假设此时我们的括号序列是确定的如何求其括号匹配的最深深度。

如果你有些许 dp 基础的话,不难想到如下做法:

考虑位置 \(i\),将区间 \([1,i]\) 内的 ( 数量设为 \(a_i\),区间 \([i+1,n]\) 内的 ) 设为 \(b_i\),此时答案应该是 \(\max_{i\in [1,n]}(\min(a_i,b_i))\)。

经过观察,我们发现:\(a_i\) 是不断增加的,\(b_i\) 是不断减少的。

证明的话考虑 \(a_i\) 的区间在不断的扩展,而 \(b_i\) 的区间在不断缩小,设扩展前的值为 \(a\),则当 \(a\) 向外扩展一格的时候只会遇到 (),故 \(a\) 扩展后的值 \(a'\) 只会等于 \(a\) 或 \(a+1\),故显然 \(a_i\) 在过程中是不断增加的。

对于 \(b_i\) 的证明同上,在这里不多赘述。

考虑答案式子 \(\max_{i\in [1,n]}(\min(a_i,b_i))\),我们可以肯定当 \(a_i = b_i\) 的时候一定会取到最大值,注意这个条件不是必要的,即最大值的情况不一定是 \(a_i = b_i\),但当 \(a_i = b_i\) 时一定可以取到最大值,证明可以考虑木桶效应。

让我们继续考虑 \(a_i=b_i\) 对应的 \(i\) 的情况数量,发现我们有且仅有一种 \(i\) 能使得 \(a_i = b_i\),证明如下:

假设我们已经到了第一次出现 \(a_i = b_i\) 的点了,考虑 \(i\) 向下扩展一格会遇到什么,它肯定只会碰到 (),如果碰到的是 (,则此时 \(b_i\) 的值一定不变,因为它对 \(b_i\) 没有贡献,但是因为 \(a_i\) 多了一个 ( 所以值会加一。如果碰到的是 ),则此时 \(b_i\) 的值必定会发生改变。故我们可以的得出,我们的每一次扩展都会必然导致 \(a_i\) 或 \(b_i\) 产生变化,不存在扩展之后 \(a_i\) 和 \(b_i\) 都不产生变化的情况。故只有一种 \(i\) 能使得 \(a_i = b_i\)。

现在有了上述的条件我们就能保证我们不会出现算重或算漏的情况了,考虑具体做法:

枚举 \(i\),记 \([1,i]\) 上 ( 的数量为 \(s_1\),记 \([1,i]\) 上 ? 的数量为 \(s_2\),记 \([i+1,n]\) 上 ) 的数量为 \(s_3\),记 \([i+1,n]\) 上 ? 的数量为 \(s_4\),枚举答案 \(j\),则当答案为 \(j\) 时的贡献就是 \(j \dbinom {s_2}{j-s_1} \dbinom {s_4}{j-s_3}\)。

那么为什么贡献是这样的呢?或者说 \(\dbinom {s_2}{j-s_1}\) 和 \(\dbinom {s_4}{j-s_3}\) 的意义是什么呢?根据我们推出的 \(a_i = b_i\) 的情况是最大值,考虑我们离当前答案 \(j\) 还差多少 (),然后将差的数量个问号变成 (),然后差的数量显然就是 \(j-s_1\) 和 \(j - s_3\),而 \(\dbinom {s_2}{j-s_1}\) 和 \(\dbinom {s_4}{j-s_3}\) 则表示的是 \(s_2\) 和 \(s_4\) 个问号中选择 \(j-s_1\) 和 \(j - s_3\) 的方案数(毕竟括号是无标号的)。

考虑预处理一下阶乘和 \(s_{1 \cdots 4}\),然后我们就能 \(\mathcal O (n^2)\) 的复杂度做完了这个题。

注意:

  • 你会发现我似乎没有讨论为什么这么扫为什么是合法的,即为什么我们能够保证我们有那么多的 ? 可选,实际上我们确实无法保证有那么多的 ? 可选,但是我们可以保证的是,如果没有那么多 ? 可选,则此时一定不会产生贡献,这一点在我们的组合数中也是有体现的。

    换言之,就是求组合数的时候需要判断一下它会不会是 \(0\)。

  • \(0! = 1\)。

代码实现

这里只给出了关键部分的代码实现,其余部分还恳请读者自己实现:

// sum1 表示 `(` 数量的前缀和
// sum2 表示 `)` 数量的前缀和
// sum3 表示 `?` 数量的前缀和
int ans = 0;
for (int i = 1; i <= n; i++) {
int s1 = sum1[i];
int s2 = sum3[i];
int s3 = sum2[n] - sum2[i];
int s4 = sum3[n] - sum3[i];
for (int j = 0; j <= n; ++j) {
ans = add(ans, mul(mul(C(s2, j - s1), C(s4, j - s3)), j));
}
}
cout << ans << endl;

题解 CF1264D1的更多相关文章

  1. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  2. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  3. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  4. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  5. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  6. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  7. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  8. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  9. CF100965C题解..

    求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...

  10. JSOI2016R3 瞎BB题解

    题意请看absi大爷的blog http://absi2011.is-programmer.com/posts/200920.html http://absi2011.is-programmer.co ...

随机推荐

  1. QLabel标签快捷键的使用

    1 from PyQt5.QtWidgets import * 2 import sys 3 4 class QlabelDemo(QDialog): 5 def __init__(self): 6 ...

  2. [selenium]取值元素文本属性样式

    前言 版本: python:3.9 selenium:4.1.5 获取元素文本 text = driver.find_element(by=By.XPATH, value=""). ...

  3. 【Nacos篇】Nacos基本操作及配置

    官方文档:https://nacos.io/zh-cn/docs/v2/ecology/use-nacos-with-spring-cloud.html 前置条件:SpringCloud脚手架 单机模 ...

  4. 《深入理解Java虚拟机》读书笔记:垃圾收集算法

    由于垃圾收集算法的实现涉及大量的程序细节,而且各个平台的虚拟机操作内存的方法又各不相同,因此本节不打算过多地讨论算法的实现,只是介绍几种算法的思想及其发展过程. 垃圾收集算法概要 1. 标记-清除算法 ...

  5. [FlareOn3]Challenge1

    打开直接f5,发现只有一个可疑函数 进入 base64??? base64解密

  6. Programming abstractions in C阅读笔记p111-p113: boilerplate

    <Programming Abstractions In C>学习第47天,p111-p113,总结如下: 一.技术总结 1.boilerplate /* * File: random.h ...

  7. quarkus数据库篇之二:无需数据库也能运行增删改查(dev模式)

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本篇内容并非数据库相关的核心知识,而是对一个 ...

  8. 用 GPT-4 给开源项目 GoPool 重构测试代码 - 每天5分钟玩转 GPT 编程系列(8)

    目录 1. 好险,差点被喷 2. 重构测试代码 2.1 引入 Ginkgo 测试框架 2.2 尝试改造旧的测试用例 2.3 重构功能测试代码 3. 总结 1. 好险,差点被喷 早几天发了一篇文章:&l ...

  9. 为何每个开发者都在谈论Go?

    本文深入探讨了Go语言的多个关键方面,从其简洁的语法.强大的并发支持到出色的性能优势,进一步解析了Go在云原生领域的显著应用和广泛的跨平台支持.文章结构严谨,逐一分析了Go语言在现代软件开发中所占据的 ...

  10. 如何对MongoDB进行测试

    一.环境搭建 关于环境搭建,最好的搭建方式,当然是脚本一键式搭建 我这里是centos6 x64版本的linux上进行构建,这个linux版本现在应该是大部分的主流服务器的标配版本 下面是安装脚本的编 ...