NOIR@ZH · NOTES & STORIES

我们逃去看海吧

记录算法与代码,也收藏游戏、故事和沿途的想法。

浏览全部文章 →

最近更新

29 篇记录

小说-神无月

第一章 只有蝉鸣的废墟 一九九八年,八月。 空气稠密得像是一锅煮坏了的胶水。 平成十年的夏天似乎致力于把地面上的一切水分都蒸发殆尽。天空呈现出一种病态的惨白,太阳不再是光源,而是一个巨大的、恶意的热辐射核心。在这个连长银都宣告破产、自杀率直线上升的年份里,连蝉的鸣叫声听起来都像是某种绝望的惨叫。 井上神社就坐落在这片惨叫声的中心。 说是神社,其实更像是一个被时代咀嚼后吐出来的残渣。鸟居上的朱漆早已剥落殆尽,露出底下发灰的木质纹理,像是某种皮肤病;手水舍的水槽里干涸已久,青苔死成了黑色的痂,只有几只不知疲倦的蚊子在腐朽的木柱间盘旋。 参道上堆满了无人清扫的落叶和枯枝。拜殿的木板有几处已经腐朽塌陷,踩上去会发出令人牙酸的“咯吱”声。整座神社像是一具被抽干了血液的干尸,在烈日下无声地腐烂。 偶尔有路人经过,也只是匆匆瞥一眼,然后加快脚步离开——没有人愿意在一座似乎有什么东西的废墟前停留太久。 事实上,井上神社确实有什么东西。 只不过,那个东西此刻正被困在更深层的腐烂里。 在这片废墟深处的社务所里,一台老旧的三洋电风扇正在发出不堪重负的“嘎吱、嘎吱”声。 “啊——————” 井上美夜子正对着风扇旋转的叶片,张大嘴巴发出毫无意义的长音。声波被扇叶切碎,变成了一种颤抖的电子音,在这个充满了霉味和陈旧榻榻米味道的房间里回荡。 她像一滩烂泥一样瘫在地上。身上穿着一套起球严重的芋色运动服,那是她高中时代的遗物,领口松垮得可以直接看到锁骨。一条灰色运动裤随随便便地卷到膝盖以上,露出苍白得有些不健康的小腿。脚边散落着半个被挖得坑坑洼洼的西瓜皮,几本过期的《周刊少年Jump》,以及无数团擦过鼻涕或不知道什么东西的纸巾。 虽然是正午,但房间里的窗帘拉得严严实实,只透进几缕昏黄的光线,照亮了空中飞舞的尘埃。 对于二十六岁的美夜子来说,这就是她的全世界。 没有因为还没有回泡沫而被取消的内定,没有那个指着她的鼻子说“你只是个空壳”的面接官,也没有那个必须要在早高峰挤上电车去扮演白领的东京。 这里只有这台连着显像管电视的世嘉土星。 美夜子翻了个身,厚如瓶底的黑框眼镜滑到了鼻尖。她抓起手柄,熟练地输入指令,八神庵紫色的火焰映在她呆滞的瞳孔里。 屏幕上显示着“ROUND 3”,她的角色只剩下最后一丝血皮,对手是大BOSS。 “干死你……干死你……”她嘟囔着,手指疯狂地敲击着按键,发出噼里啪啦的声响。那种在现实世界中早已磨灭的求生欲,此刻全部倾注在了这几个塑料按钮上。 必杀技的蓄力条正在缓慢上涨。 她屏住呼吸,瞳孔放大。 快了……快了—— “啪、啪。” 两声清脆的拍手声,突兀地穿透了蝉鸣和游戏音效,从外面的拜殿方向传来。 美夜子的手指瞬间僵在手柄上。 那是参拜礼仪中的二拍手。有人来了。 她的心脏猛地收缩了一下,那种熟悉的、令人作呕的心悸感瞬间攫取了全身。 是讨债的人吗?还是那个总是想把这块地皮骗走的远房亲戚?或者是那个多管闲事的邻居大婶? 美夜子屏住呼吸,连大气都不敢出,像只受惊的蟑螂一样缩在阴影里。她死死盯着那个关得并不严实的门缝,仿佛下一秒就会有一双皮鞋踢开这扇脆弱的门,把她从这个名为家里蹲的安全壳里拖出去暴晒。 一分钟过去了。两分钟过去了。 外面传来了脚步声,然后逐渐远去。大概只是个路过的迷路者,或者只是随便拜拜就要去别处讨生活的闲人。 美夜子长出了一口气,背后的冷汗瞬间被风扇吹得凉飕飕的。 “吓死我了……” 她嘟囔着,重新把注意力放回屏幕上。因为刚才的走神,她的角色已经被打得只剩下一丝血皮——不,是已经被打倒在地,屏幕上出现了“GAME OVER”的字样。 “可恶,这可是我打了三个小时才到的隐藏关卡……” 美夜子咬着牙,手指疯狂地敲击着“继续”按钮。 就在她即将按下“CONTINUE”的瞬间 滋——! 显像管电视发出了一声尖锐的电流音。原本绚丽的格斗画面瞬间崩解,变成了一片令人眼晕的黑白雪花点。紧接着,那个连接着世嘉土星的变压器发出了一声沉闷的爆响,一股焦糊味弥漫开来。 “诶?” 美夜子愣住了。 几秒钟后,一声凄厉的惨叫穿透了社务所的屋顶。 “我的存档啊啊啊啊啊啊啊!!” 她抓着头发,整个人跪在地上,对着漆黑一片的电视屏幕发出了灵魂的哀嚎。那是比失业还要痛苦,比被抛弃还要绝望的叫声。那是她这几个月来唯一的成就,唯一的慰藉,就这样化为了乌有。 “完了……全完了……” 美夜子把头埋在膝盖里,眼泪真切地涌了出来。 “吵死了。” 一个稚嫩却带着某种奇怪威严的声音,突然在房间里响起。 美夜子抽泣着抬起头。 她以为是幻听,或者是电视机里的残留音效。但当她透过满是雾气的眼镜看清眼前的景象时,她的喉咙像是被人掐住了一样,发出了“咯咯”的声音。 在那台刚刚报废、还散发着余热的显像管电视机顶上,坐着一个小女孩。 看起来大约只有七八岁,皮肤白得近乎透明,在昏暗的房间里散发着一种微弱的幽光。她身上穿着一件极其华丽却破旧不堪的织锦神官服,宽大的袖子像垂死的蝴蝶翅膀一样拖在地上,上面绣着的金线已经氧化发黑。下摆因为太长而胡乱地堆叠着,露出了一双悬在半空中的、赤裸的小脚。 最诡异的是,美夜子能透过小女孩的身体,隐约看到后面墙上那张发黄的日历。 她是半透明的。 那个东西正居高临下地看着美夜子。 那种眼神,就像是看着一坨粘在鞋底甩不掉的口香糖,充满了毫不掩饰的嫌弃和轻蔑。 小女孩皱起眉头,用那双并不属于这个时代的深邃眼睛环视了一圈满地狼藉的房间——西瓜皮、纸团、旧漫画、还有那个穿着芋色运动服的颓废女人。 她伸出一只半透明的小手,掩住鼻子,用清脆却冰冷的童音说道: “余的结界里,为何住着一只猪?” 美夜子张大了嘴巴,眼镜滑落了一半,挂在鼻梁上。 在那一刻,比起恐惧,她脑子里首先蹦出来的念头是: 啊,太好了。 在这该死的一九九八年夏天,在失业和逃避了六个月之后,我终于彻底疯了。 她抬起手,用力捏了一下自己的脸颊。 疼。 很疼。 不是梦。 “你……你是什么东西?”美夜子的声音在发抖,但并不是那种要被鬼怪吃掉时的恐惧——而是一种更荒诞的、世界观被砸碎之后的茫然。 “东西?”小女孩的眉毛挑了起来,那张精致的脸上浮现出一种受到冒犯的神情,“余乃建御名方富命杙神,这座井上神社的祭神。汝这无礼之徒,见了神明不行礼也就罢了,竟敢用‘东西’来称呼余?” “神……明?” 美夜子机械地重复了一遍,然后看了看周围。 社务所还是那个社务所。霉味还在,风扇还在嘎吱作响,电视还冒着焦糊味的青烟。一切都很正常,除了那个坐在电视机顶上、半透明、自称神明的小女孩。 “汝聋了吗?”小女孩不耐烦地晃了晃悬空的赤脚,“余问汝,为何住在余的结界里?” “这……这是我家的神社。”美夜子下意识地回答。 “汝家的?” 小女孩歪了歪头,似乎在回忆什么。然后她露出一个恍然的表情:“啊……是了。那个叫井上的家族,确实好几代都在这里当神职。这么说来,汝是那个家族的末裔?” “末裔”这个词让美夜子心里刺痛了一下,但她没来得及反驳, “也罢。既然汝是巫女的后人,那就勉强算作余的侍从吧。”小女孩从电视机上飘了下来——是的,飘,她的脚完全没有接触地面——然后双手抱胸,用那种居高临下的眼神看着美夜子,“余饿了。去给余准备供品。” “供……供品?” “对。最好是羊羹。如果没有的话,红豆大福也行。余不挑食——虽然汝看起来也不是什么能供奉得起好东西的穷酸货色。” 美夜子张了张嘴,又闭上。 她看了看报废的游戏机,看了看满地狼藉,再看了看眼前这个颐指气使的幼女幽灵。 最后,她长长地叹了口气,整个人又瘫回了地上。 “你要吃就吃吧。”她有气无力地说,“反正我已经什么都没有了。要命的话就拿去好了。这破命也不值钱。” 小女孩眯起了眼睛。 “汝……不怕余?” “怕。”美夜子翻了个身,背对着她,“但是比起鬼,我更怕电话铃声。你至少不会让我去面试。” 房间里陷入了一阵诡异的沉默。 蝉鸣声重新占据了主导。 过了好一会儿,小女孩的声音再次响起,这一次少了几分傲慢,多了几分困惑: “汝……真是个奇怪的人类。” 美夜子没有回答。 她把脸埋进散发着霉味的枕头里,闭上眼睛。 外面的蝉还在叫。 而这个夏天,似乎终于要变得不那么无聊了。

↗

小说-夏夜

那几年夏天的傍晚,总是长得像一辈子也过不完。 她是从阁楼的窗户翻出去的。窗框上的绿漆已经斑驳了,像干燥的皮肤。她把裙子撩起来一点,跨过窗台,脚尖探出去,踩住外面的瓦瓦。瓦是温的,太阳晒了一整天的余温,隔着薄薄的袜子传上来,像谁的手心贴着她的脚掌。 她向前走了几步, 蹲在屋顶的斜坡上,抱住了自己的膝盖。 西边的天正在烧。像一个人在炉火前打瞌睡,脸上的光一寸一寸地暗下去,又一寸一寸地红起来。最底下是橘黄,厚厚的,像抹了一层橘子酱;往上变成橘红,稀薄一些,透出底下的粉;再往上就紫了,是那种洗了很多遍的旧绸缎的颜色,灰扑扑的紫,紫里还藏着一点不肯走的蓝。整片天就那样铺着,瓦也是灰的,远处的楼也是灰的,只有这一片橘黄和橘红,把整个屋顶都染了。她的手背上落了一层光,薄薄的,像涂了蜜。 那个人明天就走了。 这个念头像一粒石子丢进水里,涟漪一圈一圈地荡开。信她看了太多遍,折痕的地方字迹已经模糊了,那个人的名字只剩下一个大概的形状。信上写,南边的树冬天也不落叶,绿的,绿得很满,满得快要溢出来。信上写,听说那边的海很蓝。 海。 她把这个字含在嘴里,悄悄念了一下。海。轻轻的,像叹气。 她没见过海。她见过的最大的水就是运河,灰的,浑的,慢慢地流,像一个永远不着急的人。运河能流到海吗?她盯着那条灰色的带子,它拐了一个弯,被楼房挡住了,又露出来,越来越细,最后消失在橘黄和灰的交界处。她想象河一直流,流过一个又一个傍晚,流过很多她不认识的城市和田野,慢慢变宽,变蓝,变咸,变成那个人正在看的那片海。 风又来了。这一次她闭上眼睛。 她深吸一口气。把所有味道都吸进去。存起来。存在肺的最底下,存在心脏旁边那个她自己都不知道名字的地方。等她老了,等她把这件事忘了很久很久以后,这个味道还会自己跑出来,在某个傍晚,某个起风的时刻,忽然就来了,带着灰色的瓦、橘黄的天、混着水腥气和栀子香的风,带着那个人的名字,带着她十八岁那一年的全部黄昏。 她从口袋里摸出一张纸。 纸被她折了很多次,折成了一个小小的方块,边角都毛了。展开的时候,折痕像地图上的路,一条一条,交错着,把她写过的话切割成碎片。她写了很多遍。第一遍写的是名字,写完了觉得太直白,涂掉了。第二遍写了一整句话,写了又觉得太重,涂得更黑。第三遍写了一个问号,写了又觉得太轻,轻得像什么都没说。最后只剩下角落里的七个字,写得很小,但每个字都用力,纸都被笔尖划破了。 她把纸重新折好。然后爬到屋脊上,骑坐在最高的那条线上。整个小城都在脚下了。 她把那张纸塞进瓦缝里。第三行第五片瓦,从左边数起,太阳晒得最多的那一片。瓦片的边缘有一点青苔,摸上去茸茸的,像什么小动物的背。她把纸塞得很深,藏在温热的瓦片底下,像这个傍晚的一个秘密。 很多年以后,会有人掀开这片瓦吗?会有人发现这张纸吗?那时候她会在哪里?那个人会在哪里?掀开瓦片的那个人,会不会也是一个十八岁的女孩,在某个夏天的傍晚,骑着屋脊,看着西边的天一点一点暗下去?她会读懂这七个字吗?会为这七个字觉得胸口发紧吗?会觉得这个傍晚也变得很长很长,长得像一辈子也过不完吗? 她坐在屋脊上,两只手撑在身后,手心按着温热的瓦。风吹过来,把她的裙摆吹得鼓起来,像一朵倒扣的花,像一只张开的翅膀,像有什么东西要从她身体里飞出去。 她觉得自己快要飞起来了。 但她没有。她只是坐着,坐在灰色和橘黄之间,坐在天空和屋顶之间,坐在这个长得像一辈子的夏天的傍晚里。远处那颗星已经亮了,很淡,像谁在水面上点了一笔白颜料。运河还在流,灰的,慢慢地,往南,往那片她没见过的蓝。 她从口袋里摸出一颗糖,是水果硬糖,橘子味的。剥开玻璃纸的时候,纸在手里窸窣作响,皱成一团亮闪闪的小球。她把糖放进嘴里,硬硬的,在舌头上滚了一圈,甜味慢慢渗出来。 是甜的。是橘子的甜,和天边的橘黄一样甜。 她含着那颗糖,咽了一下口水,喉咙里咕咚一声,像咽下了一小块傍晚。瓦片温着她的掌心,风凉着她的脚踝,嘴里那颗糖越来越小,越来越小,甜味却越来越浓,浓得她眯起了眼睛。 她把玻璃纸展开,对着天看。纸是皱的,但光穿过它的时候,变成了金色。她把那张纸举高一点,再举高一点,举到那片橘黄里去。金色的光斑落在她脸上,落在她的眉毛上、鼻尖上、嘴唇上,像谁在亲她,轻轻地,一个一个地。 然后她把手收回来,把那张皱巴巴的玻璃纸也塞进瓦缝里,和那张纸条放在一起。第三行第五片瓦底下,太阳晒过的地方。纸条上是七个字,玻璃纸上是一个橘子味的傍晚。 她会记住这个味道的。她会的。 风最后来了一次,把她的头发吹到脸上来。发丝贴在嘴角,痒痒的,她把它们拨开,指尖沾上了一点糖的甜。她舔了一下指尖。 甜的。 她笑了一下。然后她站起身,裙子上沾了灰,拍拍,灰飞起来,在橘黄的光里飘了一瞬,就不见了。 她往阁楼走。走到边缘的时候停了一下,回头看了一眼。 第三行第五片瓦。她数了一遍。一、二、三、四、五。 然后她翻过窗台,脚踩在阁楼的地板上。地板是凉的,和瓦片完全不一样的温度。她把窗户关上,把那片橘黄关在外面,把运河的腥气、柴火的烟味、迟开的栀子的香、还有那个橘子味的傍晚,都关在外面。 她靠在窗边,听了一会儿。风在窗外呜呜地响,像在说什么,说了一遍又一遍,她听不清。 但她知道,那片瓦底下有她的七个字,有一颗糖的玻璃纸,有一个十八岁夏天的傍晚。 风会替她记住的。

↗

题解-通过操作使数组长度最小筑-脑筋急转弯,用小数踢掉大数

Problem: 100164. 通过操作使数组长度最小 思路 观察$nums[i]%nums[j]$有如下的可能性 如果$nums[i]<nums[j]$,最后只是将数组中的$nums[j]$踢出 $nums[i]>=nums[j]$则是二者踢出,$nums[i]%nums[j]$进入数组,且显然$nums[i]%nums[j]<nums[j]<=nums[i]$ 因为没有限定ij的关系,发现这种操作要么是小数将大数从数组中踢掉,要么是引入一个更小的数,将二者踢掉 最后剩下的长度应该和数组中最小值有关,且这个最小值包括操作中可能产生的 如果没有产生新的最小值,则很容易知道最后剩下的数就是原始数组中最小值的数量,然后将其两两组合,引进0,就能得到答案 如何产生更小值: 回顾1,我们将所有数与最小值相模 如果余数不为0,就为新的最小值 如果余数全为0,说明所有数都是最小值的倍数,则它们之间两两相模的最小值大于等于原始数组的最小值 我们只需要产生一个新的更小值就能把所有其他数都踢掉,此时答案是1 时间复杂度:$O(n)$ Code class Solution: def minimumArrayLength(self, nums: List[int]) -> int: m=min(nums) for num in nums: if num%m!=0:# 可以产生新的最小值 return 1 length=nums.count(m) return length//2+length%2

↗

题解-求和游戏-数学,以及简单分类证明

Problem: 1927. 求和游戏 初始思路 考虑一些等价:我们先把这个数分为两个部分$left,right$,分别是左右两边数字的和,形式化写为$\displaystyle right=\sum_{i=n/2}^{n}num_i(0<=num_i<=9)$剩下的问号数量分别为$n_{left},n_{right}$ 我们要做的实际上是对$left和right$分别操作$n_{left},n_{right}$n次,其中我们允许的操作就是对该数加上0-9的任意一个数 显然操作是对称的,所以我们只考虑有效的操作数,也就是$abs(n_{left}-n_{right})$,而且显然有效的操作数只会存在于一个数身上:如果出现在两个身上就会对称消除 我们可以先除去一些情况: 如果剩下的有效操作是奇数,则Alice一定赢,因为她一定不会选择让数相等的操作(只有一个选择),而Alice有10个合法选择 然后我们发现操作一定会让数增加,也就是说,如果存在有效操作的是较大的那个数,则一定不可能相等 现在我们只剩下了一种情况:有一个较小的数能够让双方都操作$x$次,如何让较小的数变为较大的数 设两数相差的绝对值为$gap$,每个人能操作$x$次 Alice有两个选择: 一个是积极加,在自己的回合里都加9,这样会让较小的数飞快增长,如果两数相差比较小,就能让这个数超过大点的数,从而Bob不能选出来:也就是$9x>gap$,Alice能赢 另一个是完全消极,每次都加0,这样会让数缓慢增长,单靠Bob变数增加,如果$gap>9x$,此时Alice也赢 我们惊讶地发现此时出现了9x大于小于gap,Bob都会输,就只剩下了$$9x==gap$$,所幸,我们能发现此时Bob会赢,因为不管此时Alice如何操作,Bob后手都能补齐9 Code class Solution: def sumGame(self, num: str) -> bool: n=len(num) nums=0 left=0 right=0 for i in range(n//2): if num[i]=='?': nums+=1 else: left+=ord(num[i])-ord('0') for i in range(n//2,n): if num[i]=='?': nums-=1 else: right+=ord(num[i])-ord('0') if nums%2!=0 or (left>right and nums>0) or (left<right and nums<0): #最后轮到Alice或者一定不能赢的情况 return True AliceCan=abs(nums)//2 want=abs(left-right) if AliceCan*9!=want: return True return False

↗

题解-找出叠涂元素-哈希表,两种思路,在途中检查和在最后检查

Problem: 2661. 找出叠涂元素 思路:中途检查 解法 数据量不大,看着可以在每次涂色时候查询是否合法 但是每次都查询显然会超时,我们选择一个更有效的优化 已经说明各个数各不相同,不会出现一个格子被涂两遍的情况 我们用数组来记录每一行和每一列已经被涂的格子数量,就能知道这一行列是否被全涂满 时间复杂度: $O(m*n)$ 空间复杂度: $O(m*n)$ Code class Solution: def firstCompleteIndex(self, arr: List[int], mat: List[List[int]]) -> int: matMap={} m=len(mat) n=len(mat[0]) row=[0]*m col=[0]*n for i in range(m): for j in range(n): matMap[mat[i][j]]=(i,j) for index in range(len(arr)): num=arr[index] x,y=matMap[num] row[x]+=1 col[y]+=1 if row[x]==n or col[y]==m: return index return -1 思路:最后查询 解法 我们注意到当我们知道某一行的所有元素的时候,变相知道了这一行会被什么时候涂满,既这一行存在arr中最靠后的那个索引 所以我们的任务变成了寻找最先被涂满的行或者列 对arr进行hash,记录每个元素的具体位置,再遍历行列,在遍历过程中 行列取最大值表示让这一行填满最少需要的步数 res取上述的数的最小值 时间复杂度: $O(mn)$ 空间复杂度: $O(mn)$ Code class Solution { public: int firstCompleteIndex(vector<int>& arr, vector<vector<int>>& mat) { int res=arr.size(); unordered_map<int,int>hash; for (int i=0;i<arr.size();i++){ hash[arr[i]]=i; } for (int i=0;i<mat.size();i++){ int tmp=0; for (int j=0;j<mat[0].size();j++){ tmp=max(tmp,hash[mat[i][j]]); } res=min(res,tmp); } for (int j=0;j<mat[0].size();j++){ int tmp=0; for (int i=0;i<mat.size();i++){ tmp=max(tmp,hash[mat[i][j]]); } res=min(res,tmp); } return res; } }; class Solution: def firstCompleteIndex(self, arr: List[int], mat: List[List[int]]) -> int: res=len(arr) m=len(mat) n=len(mat[0]) arrLocation={} for i,a in enumerate(arr): arrLocation[a]=i for i in range(m): nowColNeedSteps=0 for j in range(n): nowColNeedSteps=max(nowColNeedSteps,arrLocation[mat[i][j]]) res=min(res,nowColNeedSteps) for j in range(n): nowRowNeedSteps=0 for i in range(m): nowRowNeedSteps=max(nowRowNeedSteps,arrLocation[mat[i][j]]) res=min(res,nowRowNeedSteps) return res

↗