大家好,欢迎阅读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的最难题的更多相关文章

  1. Codeforces Round #239(Div. 2) 做后扯淡玩

    今天补了下 cf 239div2 顿时信心再度受挫 老子几乎已经木有时间了啊 坐着等死的命.哎!!! 到现在还只能做大众题,打铁都不行. 每次D题都是有思路敲错,尼玛不带这么坑爹的. 哎!不写了,写这 ...

  2. 初学者用js做的计算题

    1.苹果3元一个,鸭梨2元一个,桃子1元一个.现在想用200元买100个水果,在控制台中打印出来. var apple = 0; //苹果 var pear = 0; //梨 var peach = ...

  3. CodeForces 1426F Number of Subsequences

    题意 给定一个长度为 \(n\) 的串,只包含 abc 和通配符.通配符可以替换 abc 的一个.求所有得到的字符串中子序列 abc 出现的次数,对 \(10^9+7\) 取模. \(\texttt{ ...

  4. Codeforces Round #575 (Div. 3) 昨天的div3 补题

    Codeforces Round #575 (Div. 3) 这个div3打的太差了,心态都崩了. B. Odd Sum Segments B 题我就想了很久,这个题目我是找的奇数的个数,因为奇数想分 ...

  5. 刷题记录:Codeforces Round #724 (Div. 2)

    Codeforces Round #724 (Div. 2) 20210713.网址:https://codeforces.com/contest/1536. div2明显比div3难多了啊-只做了前 ...

  6. 刷题记录:Codeforces Round #719 (Div. 3)

    Codeforces Round #719 (Div. 3) 20210703.网址:https://codeforces.com/contest/1520. 没错,我是个做div3的蒟蒻-- A 大 ...

  7. 初学者--bootstrap(五)JavaScript插件(上)----在路上(6)

    jQuery 插件为 Bootstrap 的组件赋予了“生命”.可以简单地一次性引入所有插件,或者逐个引入到你的页面中. 一:首先要确认的是,单个还是全部引入: JavaScript 插件可以单个引入 ...

  8. Codeforces Round #279 (Div. 2) ABCDE

    Codeforces Round #279 (Div. 2) 做得我都变绿了! Problems     # Name     A Team Olympiad standard input/outpu ...

  9. [置顶] Codeforces Round #198 (Div. 1)(A,B,C,D)

    http://codeforces.com/contest/341 赛后做的虚拟比赛,40分钟出了3题,RP爆发. A计数问题 我们可以对每对分析,分别对每对<a, b>(a走到b)进行统 ...

随机推荐

  1. 天猫精灵对接2(OAuth 搭建)

    根据 接入方式及流程 中的说明,可知,搭建过程中,我们需要自己整一个 OAuth 的授权平台,具体说明可以参考蟋蟀大哥的文章  ASP.NET WebApi OWIN 实现 OAuth 2.0 ,我的 ...

  2. 装java开发环境 报client/jvm.dll找不到

    jdk安装成功,明明有jvm.dll就是找不到,导致eclipse打不开.此时eclipse为64位,jdk为32位:查了好多方法,不起作用.最后将jdk换位64位问题解决. 所以,一般64位的系统建 ...

  3. ubuntu 16.04 Chrome

    打开终端 输入 命令1:sudo wget http://www.linuxidc.com/files/repo/google-chrome.list -P /etc/apt/sources.list ...

  4. 老板,来几道web玩玩

    好久没做web了,没想到还能自己做出来555 [MRCTF2020]Ez_bypass 签到题8 给了源码,一个md5强类型比较,然后post传参,弱类型判断,直接1234567a绕过了 I put ...

  5. 常用物联网应用层协议(1)——先说HTTP协议

    概念 简介 HTTP是一个属于应用层的面向对象的协议,目前使用最为广泛的是HTTP1.1协议.当然,许多网站已经开始支持HTTP2.0,HTTP2复杂度高于HTTP1.1,我们先从HTTP1.1说起. ...

  6. 【6】TensorFlow光速入门-python模型转换为tfjs模型并使用

    本文地址:https://www.cnblogs.com/tujia/p/13862365.html 系列文章: [0]TensorFlow光速入门-序 [1]TensorFlow光速入门-tenso ...

  7. 详解MapReduce(Spark和MapReduce对比铺垫篇)

    本来笔者是不打算写MapReduce的,但是考虑到目前很多公司还都在用这个计算引擎,以及后续要讲的Hive原生支持的计算引擎也是MapReduce,并且为Spark和MapReduce的对比做铺垫,笔 ...

  8. BP神经网络算法程序实现鸢尾花(iris)数据集分类

    作者有话说 最近学习了一下BP神经网络,写篇随笔记录一下得到的一些结果和代码,该随笔会比较简略,对一些简单的细节不加以说明. 目录 BP算法简要推导 应用实例 PYTHON代码 BP算法简要推导 该部 ...

  9. 什么是SPI

    一.什么是SPI SPI ,全称为 Service Provider Interface,是一种服务发现机制.它通过在ClassPath路径下的META-INF/services文件夹查找文件,自动加 ...

  10. Nginx是什么?有什么用?

    一.Nginx是什么 Nginx ("engine x") 是一个高性能的 HTTP 和反向代理服务器,特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服 ...