CCF-CSP 36
...
- 签到 100
- TLE 80
- 不会实现
- TLE 30
- TLE 0
周六(12.14)四级,晚点写。。。
- 参考【题解】第 36 次 CCF-CSP 认证
第 36 次 CCF 计算机软件能力认证
梦境巡查(dream)
题目背景
传说每当月光遍布西西艾弗岛,总有一道身影默默守护着居民们的美梦。
题目描述
梦境中的西西艾弗岛由
个区域组成。梦境巡查员顿顿每天都会从梦之源( 号区域)出发,顺次巡查 号区域,最后从 号区域返回梦之源。 在梦境中穿梭需要消耗美梦能量:
- 从梦之源出发时,顿顿会携带若干初始能量;
- 从第
号区域前往下一区域( )需要消耗 单位能量,因此从第 号区域出发时,顿顿剩余的美梦能量需要大于或等于 单位; - 顺利到达第
号区域( )后,顿顿可以从当地居民的美梦中汲取 单位能量作为补给。 假设顿顿初始携带
单位美梦能量,那么首先需要保证 ,这样顿顿便可消耗 能量穿梭到 号区域、进而获得 单位能量补给。巡查 号区域后,顿顿剩余能量为 ,如果该数值大于或等于 ,顿顿便可继续前往 号区域。依此类推,直至最后消耗 单位能量从 号区域返回梦之源,便算是顺利完成整个巡查。西西艾弗岛,又迎来安宁的一夜,可喜可贺! 作为一个成熟的梦境巡查员,顿顿已经知晓初始需要携带多少能量可以保证顺利完成巡查。但在一些意外状况下,比如学生们受期末季的困扰而无法安眠,顿顿可能在某些区域无法采集足够的美梦能量。此时,便需要增加初始携带量以备万全。 具体来说,考虑一个简单的情况:在
到 号区域中,有且仅有一个区域发生意外,顿顿无法从该区域获得能量补给。如果第 号区域( )发生意外(即 变为 ),则此时为顺利完成巡查,顿顿从梦之源出发所携带的最少初始能量记作 。试帮助顿顿计算 的值。
输入格式
从标准输入读入数据。
输入共三行。
输入的第一行包含一个整数。
输入的第二行包含个整数 。
输入的第三行包含个整数 。
输出格式
输出到标准输出。
输出仅一行,包含空格分隔的个整数 。
样例
1 | 3 |
1 | 10 20 10 |
样例 1 解释
和 号区域本身便没有补给,需要携带 单位初始能量抵达 号区域,获得 号区域的大量补给后便可顺利完成巡查;
号区域发生意外,则全程没有补给,初始需携带 单位能量。
1 | 3 |
1 | 15 10 9 |
Solution
- 当时做的时候整复杂了,重复计算了最大(最小)值,没有想到这也是个可重复贡献问题,代码可以在下面看到
为解决这个问题,我们可以计算到每一个区域时剩余的能量值。
当不考虑 变为 时
记刚到
考虑 变为 时
可以注意到,这只对
1 |
|
缓存模拟(cache)
题目背景
西西艾弗岛半导体制造厂近期正在研发一种新型的处理器产品。该处理器的缓存,计划采用组相连的方式。 为了选定合适的组相连参数,我们需要对缓存的工作过程进行模拟,进而推算其性能。
处理器的缓存,存储着内存中的部分数据。当处理器的运行需要访问内存中的数据时,如果所需数据已经存储在缓存中,则可以用更为快捷的缓存访问代替内存访问,来提高处理器性能。
处理器的缓存包含若干缓存行,每个缓存行存储特定大小的数据。为了便于叙述,我们认为处理器对内存的访问,也是以缓存行为单位进行的。 以缓存行的大小为单位,将全部内存空间划分为若干块(编号从
开始),这样每个内存块的数据便可以恰好存储在一个缓存行中。
-路组相联是这样的一种缓存结构:每 个缓存行划分为一组。假设共有 个这样的组(编号从 到 ),那么编号为 的内存块仅可以被存储在编号为 的组这 个缓存行的任意一个中。其中, 表示忽略余数的整除运算, 表示整除取余数运算。一般而言, 和 是 的幂次。例如,当 、 时,编号为 的内存块可以被存储在组 的任意缓存行中;编号为 的内存块可以被存储在组 的任意缓存行中。
题目描述
具体而言,给定要读取或写入的内存块编号,即可确定该内存块可能位于的缓存行 组的编号。此时,可能存在的情况有两种:
- 该缓存行组的某个缓存行已经存储了该内存块的数据,即命中;
- 该缓存行组的所有缓存行都没有存储该内存块的数据,即未命中。
当发生命中时,处理器可以直接使用或修改该缓存行中的数据,而不需要实际读写内存。当发生未命中时,处理器需要从内存中读取数据,并将其存储到该缓存行组中的一个缓存行中,然后再使用或修改该缓存行中的数据。这个将内存中的数据读入到缓存的过程称为载入。
当执行载入操作时,如果该缓存行组中有尚未存储数据的缓存行,那么将数据存储到其中一个尚未存储数据的缓存行中,并在缓存行中记录所存储的数据块的编号;否则,按照一定方法,选择该组中的一个缓存行,并将数据存储到其中,这一过程称为替换。
当发生替换时,需要考虑被替换的缓存行是否发生过修改,即执行过写操作。如果发生过修改,则需要先将缓存行中的数据写入内存中的对应位置;然后忽略该缓存行中的数据、将新读入的数据存入其中,并记录所存储数据块的编号。
在一个缓存行组中选择被替换的缓存行的方法有很多种,该种处理器采用的是最近最少使用(LRU)方法。该方法将一个缓存行组中存有数据的缓存行排成一队,每次读或写一个缓存行时,都将该缓存行动到队列的最前端。当需要替换缓存行时,选择队列的最后一个缓存行(最久没被读写)进行替换。
本题目中,将给出一系列的处理器运行时遇到的对内存的读写指令,并假定初始时处理器的缓存为空。你需要根据上文描述的缓存工作过程,给出处理器对内存的实际读写操作序列。
输入格式
从标准输入读入数据。
输入的第一行包含空格分隔的三个整数, 分别表示组相联的路数 和组数 ,以及要处理的读写指令的数量 。 接下来 行,每行包含空格分隔的两个整数 和 。其中, 表示读写指令的类型, 表示要读写的内存块的编号。 为 或 ,分别表示读和写操作。
输出格式
输出到标准输出。
输出若干行,每行包含空格分隔的两个整数和 ,表示实际处理器对内存的读写操作。 为 或 ,分别表示读和写操作; 表示要读写的内存块的编号。
样例
1 | 4 8 8 |
1 | 0 0 |
样例解释
该处理器的缓存为
路组相联,共有 组。初始时,处理器的缓存为空。共需要处理 条指令: 第
条指令为读取内存块 ,未命中,要实际读取内存块 ,并存储到组 的一个缓存行;
第条指令为读取内存块 ,未命中,要实际读取内存块 ,并存储到组 的另一个缓存行;
第条指令为写入内存块 ,未命中,要实际读取内存块 ,并存储到组 的第三个缓存行,然后根据指令在缓存中对其进行修改;
第条指令为读取内存块 ,命中,直接从缓存中调取数据;
第条指令为写入内存块 ,命中,直接修改缓存中的数据;
第条指令为读取内存块 ,未命中,要实际读取内存块 ,并存储到组 的第四个缓存行;
第条指令为写入内存块 ,未命中,此时组 中的 个缓存行都保存了数据:最近使用的是保存有内存块 的缓存行,其次是保存有内存块 的缓存行,然后是 ,最后是 ,因此选择替换保存有内存块 的缓存行。注意到该缓存行在执行第 条指令时被修改过,因此需要先将其写入内存,然后再读取内存块 的数据存储到该缓存行中;
第条指令为读取内存块 ,未命中,此时组 中的 个缓存行都保存了数据,按照同样的办法,选择保存有内存块 的缓存行替换。注意到该缓存行未被修改过,因此可以直接读取内存块 的数据存储到该缓存行中。
Solution
其实简单,但是场上没写出来,一个是没心思去读题干,另一个是样例没看明白。这里其实应该提一下如果没有读写内存操作就不输出,我当时没有去对输入输出的条数,看样例解析和输出对不上人傻了。
1 |
|
我的伞兵代码
1 |
|
1 |
|
1 |
|
1 |
|