刷题记录:LC1997-访问完所有房间的第一天
LC1997-访问完所有房间的第一天
题意
- 这里有 n 个房间,从 0 到 n-1 编号。
- 你每天访问一个房间,第 0 天访问第 0 号房间。
- 接下来,你访问房间的【次序】将根据下面的【规则】决定:
- 假设某一天,你访问 i 号房间。
- 如果算上本次访问,访问 i 号房间的次数为【奇数】 ,那么 第二天 需要访问 nextVisit[i] 所指定的房间,其中【0 <= nextVisit[i] <= i 】。注意【0 <= nextVisit[i] <= i】,如果访问次数为【奇数】,我们就要回溯。
- 如果算上本次访问,访问 i 号房间的次数为【偶数】,那么 第二天 需要访问 (i + 1) mod n 号房间。即,访问下一号房间。
- 求出【访问完所有房间的天数】,模1e9+7。
思路
首先
我们注意到一个事情啊,如果对当前这个房间的访问次数为奇数,那么明天就必须返回更小的房间;如果对当前房间的访问次数为偶数,明天才能堪堪访问紧邻的下一号房间,这样一点一点往前爬。
所以不难想到,【访问完所有房间的天数】就是【访问最后一个房间的天数】。
然后
- 设 dp[i] 为【第一次访问 i 号房间的天数】。
- 如果在 dp[i] 这一天第一次访问 i 号房间,那么【i-1 号房间的访问次数】应该是偶数,只有这样才能从 i-1 爬到 i。
- 那么,我们怎么从 i-2 爬到 i-1的呢?i-2 号房间的访问次数,也需要是偶数。
- i-3、i-4、……。为了爬到 i 号房间,以前所有房间的访问次数,都需要是偶数。
- 在 dp[i]+1 这一天,我们返回了 nextVisit[i] 号房间。如果 nextVisit[i]≠i 即 nextVisit[i]<i,除了 i 和 nextVisit[i] 号房间的访问次数是奇数,其他房间全是偶数(包括0次,未访问)。
- 请集中精神仔细看,关键来了:
- 我们现在的情况,像不像【刚刚访问 nextVisit[i] 号房间】的情况?也是 nextVisit[i] 刚刚变成奇数,其他房间都是偶数。i>nextVisit[i],对接下来爬到 nextVisit[i]+1 毫无影响。不能说是很像,只能说一模一样!
- 如果我们想从 i 爬到 i+1,我们需要第二次访问 i 号房间,即,从 nextVisit[i] 爬到 i。我们已经经历一遍这个过程了,就是在第一次访问 i 号房间,从 nextVisit[i] 爬到 i 的过程。
- 因此,这一段过程需要 dp[i]-dp[nextVisit[i]] 的天数,直接相减。
- 此时,我们已经第二次到达 i 号房间。再花最后一天爬到 i+1 号房间,我们就又往前进了一步。
- 总结整个过程:爬到 i,dp[i] 天;从 i 到 nextVisit[i],1 天;从 nextVisit[i] 再次到 i,dp[i]-dp[nextVisit[i]] 天;从 i 到 i+1,1 天。
- 得到递推方程:
dp[i+1]=dp[i]+1+dp[i]-dp[nextVisit[i]]+1。 - 整理:
dp[i+1]=2*dp[i]-dp[nextVisit[i]]+2。 - 别急,还有一种情况哦:如果 nextVisit[i]=i 怎么办?公式变成
dp[i+1]=dp[i]+2,用 dp[i] 天到达 i,花一天时间原地打转,再花一天时间前进一步,公式也没问题。 - 所以就 ok 了!
另一种神乎其技的解法
- 设 f[i] 为【从 第一次访问 i 到 第一次访问 i+1】的天数,即 dp[i+1]-dp[i]。
- 我们在 dp[i] 这一天访问了 i,下一天会回到 j=nextVisit[i]。我们已经知道,情况和【第一次访问 j=nextVisit[i]】一模一样。
- 所以,从 j 爬到 j+1,需要 f[j] 天。爬到 j+1 后,j+1 的访问次数变成奇数,而 j 因为【要往前爬】变成偶数。此时,是不是又和【第一次访问 j+1】一模一样了?
- 所以,从 j+1 爬到 j+2,需要 f[j+1] 天。接下来到 j+3,需要 f[j+2] 天。……。接下来到 i,需要 f[i-1] 天。
- 我们得到了什么结论?从 j=nextVisit[i] 再次爬到 i,需要 \(\sum_{k=j}^{i-1}f[k]\) 天。加上从 i 到 j=nextVisit[i] 的 1 天、第二次到 i 后再进一步的 1 天,【从 第一次访问 i 到 第一次访问 i+1】需要 \(2+\sum_{k=j}^{i-1}f[k]\) 天。
- 我们得到了递推方程:\(f[i]=2+\sum_{k=j}^{i-1}f[k]\)。
- 求和,可以用前缀和去优化。设 \(sum[i]=\sum_{k=0}^{i-1}f[i]\),则
sum[i+1]-sum[i]=f[i]=2+sum[i]-sum[j]=2+sum[i]-sum[nextVisit[i]]。 - 整理一下:
sum[i+1]=2*sum[i]-sum[nextVisit[i]]+2。好家伙,这不就是那个 dp 的递推公式吗?原来 sum 就是 dp! - sum 就是 dp 的考证:我们在第0天访问了 0 号房间。要去访问 i 号房间,天数为 0+【从第一次访问 0 到第一次访问 1,f[0]】+【从第一次访问 1 到第一次访问 2,f[1]】+……+【从第一次访问 i-1 到第一次访问 i,f[i-1]】,可不就是sum[i]嘛!
- 现在,我们已经完整地了解了,该题的两套解法。
刷题记录:LC1997-访问完所有房间的第一天的更多相关文章
- 刷题记录:[De1ctf] shell shell shell
目录 刷题记录:[De1ctf] shell shell shell 一.知识点 1.源码泄露 2.正则表达式不完善导致sql注入 3.soapclient反序列化->ssrf 4.扫描内网 5 ...
- 刷题记录:[ByteCTF 2019]EZCMS
目录 刷题记录:[ByteCTF 2019]EZCMS 一.知识点 1.源码泄露 2.MD5长度扩展攻击 3.php://filter绕过正则实现phar反序列化 刷题记录:[ByteCTF 2019 ...
- 刷题记录:[LCTF]bestphp's revenge
目录 刷题记录:[LCTF]bestphp's revenge 一.知识点 1.SoapClient触发反序列化导致ssrf 2.serialize_hander处理session方式不同导致sess ...
- 刷题记录:[CISCN2019 总决赛 Day2 Web1]Easyweb
目录 刷题记录:[CISCN2019 总决赛 Day2 Web1]Easyweb 一.涉及知识点 1.敏感文件泄露 2.绕过及sql注入 3.文件上传:短标签绕过php过滤 刷题记录:[CISCN20 ...
- 刷题记录:[网鼎杯]Fakebook
目录 刷题记录:[网鼎杯]Fakebook 一.涉及知识点 1.敏感文件泄露 2.sql注入 二.解题方法 刷题记录:[网鼎杯]Fakebook 题目复现链接:https://buuoj.cn/cha ...
- $2019$ 暑期刷题记录1:(算法竞赛DP练习)
$ 2019 $ 暑期刷题记录: $ POJ~1952~~BUY~LOW, BUY~LOWER: $ (复杂度优化) 题目大意:统计可重序列中最长上升子序列的方案数. 题目很直接的说明了所求为 $ L ...
- PKUWC&SC 2018 刷题记录
PKUWC&SC 2018 刷题记录 minimax 线段树合并的题,似乎并不依赖于二叉树. 之前写的草率的题解在这里:PKUWC2018 minimax Slay the Spire 注意到 ...
- DP刷题记录(持续更新)
DP刷题记录 (本文例题目前大多数都选自算法竞赛进阶指南) TYVJ1071 求两个序列的最长公共上升子序列 设\(f_{i,j}\)表示a中的\(1-i\)与b中色\(1-j\)匹配时所能构成的以\ ...
- DP刷题记录
目录 dp刷题记录 codeforces 706C codeforces 940E BZOJ3997 POJ2279 GYM102082B GYM102082D codeforces132C L3-0 ...
随机推荐
- vue2升级vue3:vue2 vue-i18n 升级到vue3搭配VueI18n v9
项目从vue2 升级vue3,VueI18n需要做适当的调整.主要是Vue I18n v8.x 到Vue I18n v9 or later 的变化,其中初始化: 具体可以参看:https://vue- ...
- 基恩士的浓淡补正算法(Shading Correction Filter)的模拟实现。
知道这个算法应该有很久了,主要当时在意2个事情,一个是这个名字的翻译是在是搞笑,第二是这个算法的效果.不过一直以来都十分好奇这个算法是怎么实现的.因为之前一直无法实际的用基恩士的软件平台用不同的图片去 ...
- 一图读懂k8s informer client-go
概述 为什么要有k8s informer 我们都知道可以使用k8s的Clientset来获取所有的原生资源对象,那么怎么能持续的获取集群的所有资源对象,或监听集群的资源对象数据的变化呢?这里不需要轮询 ...
- FTP安装及使用
通过网络传输数据的手段 1. ssh 2. http 3. nfs 4. rsync 5. ftp 6. samba ftp的简介: 1. ftp是应用层协议,是基于TCP 2. 使用21端口 FTP ...
- UiPath文本操作Set Text的介绍和使用
一.Set Text的介绍 向输入框/文本框写入文本的一种操作 二.Set Text在UiPath中的使用 1.打开设计器,在设计库中新建一个Sequence,为序列命名及设置Sequence存放的路 ...
- 链表设计与Java实现,手写LinkedList这也太清楚了吧!!!
链表设计与实现 在谈链表之前,我们先谈谈我们平常编程会遇到的很常见的一个问题.如果在编程的时候,某个变量在后续编程中仍需使用,我们可以用一个局部变量来保存该值,除此之外一个更加常用的方法就是使用容器了 ...
- ArrayList集合概述和基本使用和ArrayList集合的常用方法和遍历
什么是ArrayList类 java.util.ArrayList 是大小可变的数组的实现,存储在内的数据称为元素.此类提供一些方法来操作内部存储 的元素. ArrayList 中可不断添加元素,其大 ...
- CF1132D Stressful Training
题目链接 题目 见链接. 题解 方法一 知识点:贪心,优先队列,二分. 显然,这道题可以用二分答案做.check 函数可以用小根堆,让维持时间最小的先充电. 但是不优化这道题会炸.有两个关键优化:一个 ...
- 攻防世界MISC进阶区--39、40、47
39.MISCall 得到无类型文件,010 Editor打开,文件头是BZH,该后缀为zip,打开,得到无类型文件,再改后缀为zip,得到一个git一个flag.txt 将git拖入kali中,在g ...
- 7 什么是dubbo
什么是dubbo 快速入门dubbo 了解什么是dubbo之前,我们得先了解什么是分布式系统? <分布式系统原理与范型>定义: 分布式系统是若干独立计算机的集合,这些计算机对于用户来说就像 ...