codeforces 1426F,初学者也能做,div3的最难题
大家好,欢迎阅读codeforces专题。
今天选择的题目是Div3比赛的最后一题,也是最难的一道题。选这道题的主要原因是帮助大家建立信心,因为有些小伙伴给我反应说之前选择的题目有些难了,觉得自己可能应付不了codeforces的题目。所以今天特地选了Div3比赛当中的最难题来给大家一点信心。
Div3比赛是难度最低的比赛,面向的是算法的初学者,非常适合大家作为入门练习。由于是最后一道题,所以这题的通过人数不是很多,大概是530人。但是这题并不很难,我感觉大约和我们Div2中的C题相当。
链接:https://codeforces.com/contest/1426/problem/F
废话不多说了,让我们直接看题吧。
题意
给定一个只有abc和?的字符串,其中的?可以被任意替换成a、b或者c。我们假设?一共有k个,这样我们一共可以得到个不同的字符串。
要求所有这些字符串当中拥有的abc子序列的个数,子序列是指原串在不改变元素相对顺序的情况下通过删除元素得到的子集。比如说baacbc拥有两个abc的子序列,分别是下标组合(2,5,6)和(3,5,6)。
由于最终的数量可能会很大,要求这个结果对取模。
样例
输入一共有两行,第一行给定一个整数n(),表示字符串的长度。第二行输入长度为n的字符串,要求返回abc子序列的个数。
对于第一个样例的解释:
题解
这题看起来比较复杂,想要直接想出解法来正面攻破还是不太容易的。所以我们先把一些条件放一放,先从最简单的思路入手。
最简情况
首先我们需要解决一个问题,就是当不存在?的时候,我们如何求出abc子序列的个数呢?比如acabac,我们怎么求出其中abc子序列的数量呢?答案是2,这个2是怎么来的呢?
因为要保证b出现在a的后面,c出现在b的后面,我们当然可以直接用三重循环去枚举所有的组合,但这显然不是最好的方法。我们仔细想一下,这是一个有限制的组合问题,很容易发现每一个字母b都可以和它之前的所有a组成ab的配对,同样每个字母c也可以和之前的每个序列ab组成abc的子序列。
那么我们可以使用动态规划的思路来求解,我们用三个变量d[0], d[1], d[2],分别维护a、ab和abc串的数量。当我们遇到a的时候,d[0]加1,遇到b的时候呢?d[1]加1吗?显然不对,因为b可以和之前的每一个a都组成ab,所以d[1]应该加的不是1而是d[0]。同样,遇到c的时候,也一样,d[2]应该加上d[1]。
这样我们就可以求出在没有?时满足条件的子序列的数量了。
d = [0, 0, 0]
for i in range(n):
if s[i] == 'a':
d[0] += 1
elif s[1] == 'b':
d[1] += d[0]
else:
d[2] += d[1]
进阶使用
现在我们已经解决了没有?出现时的情况,那么加上?的话应该怎么办呢?
我们进一步来分析,对于每一个?来说它其实都有三种选择。比如a?c,展开之后会有aac,abc,acc这三种情况。那么我们能不能在遇到?的时候把这三种情况全部都考虑进去呢?
当我们遇到?的时候,我们把d数组拷贝成三份,分别用来存储?=a, ?=b 和 ?=c的情况。我们先把数组d拷贝成d1、d2和d3。我们用这三个数组代表?取三种不同取值的情况,最后再把它们合并到一起,变成新的数组d_new。
因为d1, d2和d3其实就是d,所以我们把它们最后整合在一起之后依然可以用d来表示。
到这里都没有问题对吧,其实这里藏了一个trick。这个trick非常隐蔽,很难发现。就是我们在?=a的情况下,我们这里d1[0] += 1其实是不对的,我们要加的不是1。我们来举一个例子就明白了,比如a??c。
在这个字符串当中我们存在两个?,对于第一个?而言,它是a的时候d[0] += 1这没有问题。但是当遇到第二个?的时候问题就来了,对于第一个问号等于a的情况而言,由于第二个问号有三种取值,那么带来的a的数量其实应该是3,而不是1。我们只加了1就是错误的。我们也可以反过来理解,对于第一个问号,我们整合了三种可能性。当我们第二个问号设置为a的时候,其实是背后是第一个问号带来的3种可能,所以这里要加的就不是1而是3。如果我们有3个问号呢?第三个问号显然加的就是9了。也就是说对于第k个问号而言,。
这个trick注意到了,那么AC也就是顺理成章的事了。
n = int(input())
s = input()
ret = 0
Mod = int(1e9+7)
dp = [0, 0, 0]
cnt = 1
for i in range(n):
if s[i] == 'a':
dp[0] += cnt
elif s[i] == 'b':
dp[1] += dp[0]
elif s[i] == 'c':
dp[2] += dp[1]
else:
dp[2] = (3 * dp[2] + dp[1]) % Mod
dp[1] = (3 * dp[1] + dp[0]) % Mod
dp[0] = (3 * dp[0] + cnt) % Mod
cnt = (cnt * 3) % Mod
print(dp[2] % Mod)
今天选择的是div3比赛当中通过人数最少,也就是最难的一题。但我们做下来会发现其实也就用到了最基础的动态规划的思想,虽然不容易想到解,但是难度其实还可以。
所以如果你想要提升自己的算法能力,但是又担心题目太难自己无法胜任的话,可以考虑做一做div3的一些比赛。相信我不会太难的。
今天的文章就到这里,衷心祝愿大家每天都有所收获。如果还喜欢今天的内容的话,请来一个三连支持吧~(点赞、关注、转发)
codeforces 1426F,初学者也能做,div3的最难题的更多相关文章
- Codeforces Round #239(Div. 2) 做后扯淡玩
今天补了下 cf 239div2 顿时信心再度受挫 老子几乎已经木有时间了啊 坐着等死的命.哎!!! 到现在还只能做大众题,打铁都不行. 每次D题都是有思路敲错,尼玛不带这么坑爹的. 哎!不写了,写这 ...
- 初学者用js做的计算题
1.苹果3元一个,鸭梨2元一个,桃子1元一个.现在想用200元买100个水果,在控制台中打印出来. var apple = 0; //苹果 var pear = 0; //梨 var peach = ...
- CodeForces 1426F Number of Subsequences
题意 给定一个长度为 \(n\) 的串,只包含 abc 和通配符.通配符可以替换 abc 的一个.求所有得到的字符串中子序列 abc 出现的次数,对 \(10^9+7\) 取模. \(\texttt{ ...
- Codeforces Round #575 (Div. 3) 昨天的div3 补题
Codeforces Round #575 (Div. 3) 这个div3打的太差了,心态都崩了. B. Odd Sum Segments B 题我就想了很久,这个题目我是找的奇数的个数,因为奇数想分 ...
- 刷题记录:Codeforces Round #724 (Div. 2)
Codeforces Round #724 (Div. 2) 20210713.网址:https://codeforces.com/contest/1536. div2明显比div3难多了啊-只做了前 ...
- 刷题记录:Codeforces Round #719 (Div. 3)
Codeforces Round #719 (Div. 3) 20210703.网址:https://codeforces.com/contest/1520. 没错,我是个做div3的蒟蒻-- A 大 ...
- 初学者--bootstrap(五)JavaScript插件(上)----在路上(6)
jQuery 插件为 Bootstrap 的组件赋予了“生命”.可以简单地一次性引入所有插件,或者逐个引入到你的页面中. 一:首先要确认的是,单个还是全部引入: JavaScript 插件可以单个引入 ...
- Codeforces Round #279 (Div. 2) ABCDE
Codeforces Round #279 (Div. 2) 做得我都变绿了! Problems # Name A Team Olympiad standard input/outpu ...
- [置顶] Codeforces Round #198 (Div. 1)(A,B,C,D)
http://codeforces.com/contest/341 赛后做的虚拟比赛,40分钟出了3题,RP爆发. A计数问题 我们可以对每对分析,分别对每对<a, b>(a走到b)进行统 ...
随机推荐
- mysql explain 查询处理的结果详解
本文转自 https://blog.csdn.net/boss_way/article/details/91416887 在日常工作中,我们会有时会开慢查询去记录一些执行时间比较久的SQL语句,找出这 ...
- Helium文档10-WebUI自动化-Text识别网页上的任何文本或标签
前言 Text关键字的作用是识别网页上的文字,在一般UI查找中使用率非常高,但是需要注意,如果网页上有相同的文字,那么只能识别到第一个 入参介绍 以下是Text的源码 有5个如参:后面4个参数是上下左 ...
- docker启动redis并设置密码
docker启动redis并设置密码: docker run -d --name redis -p 6379:6379 redis --requirepass "password" ...
- LIS初级推算(最长上升子序列问题)
所谓LIS,就是Longest Increasing Subsequence问题 注意,子序列不一定是连续的,举个例子:对于序列10,9,2,3,5,4,7,9,101,18,其中的LIS就是2,3, ...
- 读书摘要观后感与总结:《Glibc内存管理:ptmalloc2源代码分析》
更新中 在Linux平台下做漏洞利用的时候,针对于Heap部分总是有些不求甚解,下面开个博文来记录下<Glibc内存管理:ptmalloc2源代码分析>这本书的读后感和收获,一些简单的点将 ...
- linux下生成动态库和链接动态库
1.生成动态库 src/test.h #ifndef _TEST_H_HH #define _TEST_H_HH void print(); #endif src/test.cpp #include ...
- STM32入门系列-库目录及文件介绍
已经介绍了过了CMSIS标准,ST公司按照这个标准设计了一套基于STM32F10x的固件库,我们可以直接在ST公司的官网进行下载,现在给大家STM32最新固件库v3.5,在网盘上给大家提供了下载包,链 ...
- mq_open失败,Invalid argument
经四处查找,终于发现原因: (1)attr.mq_maxmsg 不能超过文件 /proc/sys/fs/mqueue/msg_max 中的数值,我的机器上面是10. (2)attr.mq_msgsiz ...
- 20200722_Oracle添加表空间、用户,用户授权
--创建表空间 CREATE TABLESPACE aifu --表空间名 aifu LOGGING DATAFILE 'D:\dev_config\OracleTableSpaces\aifu.DB ...
- XX-Net 解决IPV6 不稳定,时好时坏。
一.启动IPV6 1.重置: netsh interface Teredo set state disable netsh interface Teredo set state type=defaul ...