首页 > 其他分享 >P7914 做题笔记

P7914 做题笔记

时间:2023-10-16 20:22:37浏览次数:35  
标签:dp2 P7914 笔记 len dpb dpa 505 mod

题目链接

CSP 考前做下历年真题。

转移很多,我刚开始设 $dp1[i][j]$ 为 $i$ 到 $j$ 合法的方案数,$dp2[i][j]$ 为左边一段 $*$,右边是合法的方案数,以及 $dp3[i][j]$,右边是 $*$,左边合法。

然后就进坑了,比如 $()()()$,会在第二个位置统计一下,(两个合法的字符串拼起来)也会在第四个位置统计一下,苦思冥想了 $1$ 分钟,得出解决方案:将 $dp1[i][j]$ 拆成两个分别是 $dpa[i][j]$ 和 $dpb[i][j]$,前者表示最外部是一个互相匹配的括号,后者表示的是符合的,但左右不是配对的方案数。

转移略有些复杂。

#include <bits/stdc++.h>
#define int long long
#define For(i, a, b) for (int i = (a); i <= (b); i ++)
#define foR(i, a, b) for (int i = (a); i >= (b); i --)
using namespace std;
int n, k;
int dp2[505][505], dp3[505][505];
int dpa[505][505], dpb[505][505];
//dpa[i][j]:[i, j] 合法方案数,且字符串两侧是配对的 '(' ')'
//dpb[i][j]:[i, j] 合法方案数,且字符串两侧不是配对的 '(' ')'
bool c[505][505];
char s[505];
const int mod = 1000000007;
bool check (char a, char b) {
    if (a == b || a == '?') return 1;
    return 0;
}
void solve () {
    scanf ("%d%d%s", &n, &k, s + 1);
    For (i, 1, n)
        if (s[i] == '?' || s[i] == '*') c[i][i] = 1;
    For (i, 1, n) c[i][i - 1] = 1;
    For (len, 2, n) {
        For (i, 1, n - len + 1) {
            int j = i + len - 1;
            c[i][j] = (c[i][i] && c[i + 1][j]);
        }
    }
    For (len, 2, n) {
        For (i, 1, n - len + 1) {
            int j = i + len - 1;
            //dp2[i][j]:左边若干个 *,右边是符合要求的
            //dp3[i][j]:右边若干个 *,左边是符合要求的
            For (l, 1, min (len - 1, k) ) {
                if (c[i][i + l - 1]) {
                    dp2[i][j] = dp2[i][j] + (dpa[i + l][j] + dpb[i + l][j]) % mod;
                    if (dp2[i][j] >= mod) dp2[i][j] -= mod;
                }
                if (c[j - l + 1][j]) {
                    dp3[i][j] = dp3[i][j] + (dpa[i][j - l] + dpb[i][j - l]) % mod;
                    if (dp3[i][j] >= mod) dp3[i][j] -= mod;
                }
            }
            //dp1[i][j]:区间 [i, j] 中符合要求的括号序列的数量
            if (c[i + 1][j - 1] && check (s[i], '(') && check (s[j], ')') && len - 2 <= k) dpa[i][j] = 1;
            For (l, i, j - 1) {
                dpb[i][j] = dpb[i][j] + dpa[i][l] * dpa[l + 1][j] % mod;
                if (dpb[i][j] >= mod) dpb[i][j] -= mod;
                dpb[i][j] = dpb[i][j] + dpa[i][l] * dpb[l + 1][j] % mod;
                if (dpb[i][j] >= mod) dpb[i][j] -= mod;
            }
            if (check (s[i], '(') && check (s[j], ')') )
                dpa[i][j] = (dpa[i][j] + dpa[i + 1][j - 1] + dpb[i + 1][j - 1] + dp2[i + 1][j - 1] + dp3[i + 1][j - 1]) % mod;
            For (l, 1, j - 1) {
                dpb[i][j] = (dpb[i][j] + (dpa[i][l] * dp2[l + 1][j]) % mod) % mod;
                if (dpb[i][j] >= mod) dpb[i][j] -= mod;
            }
        }
    }
    cout << (dpa[1][n] + dpb[1][n]) % mod;
}
signed main () {
    int _ = 1;
//    cin >> _;
    while (_ --) {
        solve ();
        cout << '\n';
    }
    return 0;
}

 

标签:dp2,P7914,笔记,len,dpb,dpa,505,mod
From: https://www.cnblogs.com/Xy-top/p/17768251.html

相关文章

  • 2023/10/16 学习笔记
    网络层协议与解析网络层的功能: 定义了基于IP协议的逻辑地址  连接不同的媒介类型 选择数据通过网络的最佳路径IP数据包格式: 注解:版本(4) 指IP协议版本。并且通过双方使用的版本必须一致,目前我们使用的是ipv4,表示为0100十进制是4首部长度(4) IP数据包的包头长......
  • 数据库系统笔记 - chap2 - 关系模型
    关系数据结构关系代数Asetoffundamentaloperationstoretrieveandmanipulatetuplesinarelation.Theseoperationstakeoneorsomerelationsasinputs,andoutputsanewrelation.并、交、差、笛卡尔积与集合运算相似。选择(Select)行视角,选择出符合条件的若......
  • 数据库系统笔记 - chap3 - SQL
    IntroductiontoSQLSQL(StructuredQueryLanguage),是关系数据库的标准查询语言。SQL的特点:综合统一SQL集数据定义语言(DDL),数据操纵语言(DML),数据控制语言(DCL)功能于一体。高度非过程化SQL只要提出“做什么”,而无须指明“怎么做”,因此无须了解存取路径。存取路径的选择......
  • 微机原理笔记 - chap1 - 绪论
    Intel微处理器的发展1978年:8086/8088微处理器出现,首枚16位微处理器。微型计算机概述计算机加电以后,首先运行BIOS(BasicInputOutputSystem)系统,进行硬件的检查、初始化(加电时寄存器的内容是随机的)、给操作系统提供编程接口等。通过硬件驱动程序、BIOS/UEFI提供的编程......
  • 微机原理笔记 - chap2 - Intel单核/多核处理器
    单核处理器(8086/8088)8086/8088功能特性第一次将流水线思想引进微处理器:指令级流水。存储器分段管理机制引入处理器,扩大寻址能力。内存地址分段:寄存器最多存16位,故有些寄存器用来当段寄存器,代表着地址的高16位(低4位默认为0)。再加上段内偏移寄存器的值(低16位),就可以......
  • 微机原理笔记 - chap3 - Intel处理器指令系统及汇编语言
    汇编语言基础数据定义:数据传送、算术运算、跳转指令MOV指令“先目的操作数,再源操作数。”MOV指令需要遵循的规则:两个操作数的尺寸必须一致。两个操作数不能同时为内存操作数。movreg,regmovmem,regmovreg,memmovmem,immmovreg,immmovvar2,var1......
  • 数据库系统笔记 - chap1 - 绪论
    数据库发展史人工管理阶段(1950)\(\Rightarrow\)文件系统阶段(1950-1960)\(\Rightarrow\)数据库系统阶段(1960-)数据库管理系统(DBMS)的出现,使得数据存储、数据管理和数据应用分离。数据库管理系统采用外模式-模式-内模式的三级模式,外模式/模式和模式/内模式的两级映象结构。数......
  • 《Mastering the FreeRTOS Real Time Kernel》读书笔记(7)事件组
    8.事件组之前已经介绍了多任务之间的交流桥梁,包括了队列和信号量。与队列和信号量不同:事件组允许任务在“阻塞”状态下等待一个或多个事件的组合发生。事件组在事件发生时,取消等待同一事件或事件组合的所有任务的阻塞状态。事件组的这些独特属性可用于同步多个任务、向多个任务......
  • 《Mastering the FreeRTOS Real Time Kernel》读书笔记(6)资源管理
    7.资源管理(互斥量)在多任务系统中,如果一个任务开始访问资源,但在从运行状态转换出来之前没有完成访问,则可能会出现错误。如果任务使资源处于不一致状态,则任何其他任务或中断对同一资源的访问都可能导致数据损坏或其他类似问题。这里的资源管理,应该是指计算机的外设资源,比如LCD显示......
  • Java常见集合类学习笔记
    List1.ArrayListVectorLinkedList区别​ ArrayList和Vector底层实现基本相同,都是基于数组实现的,只是Vector的方法用synchronized修饰;所以ArrayList是线程不安全的,Vector是线程安全的。​ LinkedList底层基于双向链表实现,方法没有用synchronized修饰,线程不安全。2.数组和......