1 条题解

  • 0
    @ 2025-5-25 22:53:31

    描述

    Mo和Larry发明了一种加密消息的方法。他们首先秘密决定列数,然后将消息(仅包含字母)按列写入,并用额外的随机字母填充,以形成一个矩形的字母阵列。例如,如果消息是 “There’s no place like home on a snowy night” 且列数为55,Mo会写下:

    t o i o y  
    h p k n n  
    e l e a i  
    r a h s g  
    e c o n h  
    s e m o t  
    n l e w x  
    

    注意,Mo只包含字母并将它们全部转换为小写。在此示例中,Mo使用字母“x”填充消息以形成矩形,但他也可以使用任何其他字母。

    然后,Mo通过按行交替从左到右和从右到左书写字母,将消息发送给Larry。因此,上述消息将被加密为:

    toioynnkpheleaigshareconhtomesnlewx  
    

    你的任务是为Larry从加密的消息中恢复原始消息(包括任何额外的填充字母)。

    输入

    每个输入集包含多组数据。每组输入由两行组成。第一行包含一个范围在222020之间的整数,表示使用的列数。第二行是一个最多包含200200个小写字母的字符串。最后一个输入集之后是一行包含单个00,表示输入结束。

    输出

    每个输入集应生成一行输出,给出原始的明文消息,不含空格。

    问题重述

    Mo和Larry发明了一种加密消息的方法。具体步骤如下:

    1. 加密过程:

      • 首先,他们秘密决定一个列数(例如5)。
      • 将原始消息(仅包含字母,且已转换为小写)按列写入,形成一个矩形的字母阵列。如果字母数量不足以填满矩形,则用随机的小写字母填充。
      • 然后,按行交替从左到右和从右到左读取字母,形成加密后的字符串。

      例如,消息“There’s no place like home on a snowy night”和列数为5时:

      • 按列写入:
        t o i o y  
        h p k n n  
        e l e a i  
        r a h s g  
        e c o n h  
        s e m o t  
        n l e w x  
        
      • 然后按行交替方向读取:
        • 第一行从左到右:toioy
        • 第二行从右到左:nnkph
        • 第三行从左到右:eleai
        • 第四行从右到左:gshar
        • 第五行从左到右:econh
        • 第六行从右到左:tomes
        • 第七行从左到右:nlewx
      • 组合起来:toioynnkpheleaigshareconhtomesnlewx
    2. 解密任务:

      • 给定列数和加密后的字符串,恢复原始的矩形字母阵列(包括填充字母)。
      • 输出原始的明文消息(按列读取)。

    输入输出示例

    输入:

    5
    toioynnkpheleaigshareconhtomesnlewx
    0
    

    输出: theresnoplacelikehomeonasnowynightx

    解题思路

    1. 理解加密的逆过程:

      • 加密时是按行交替方向(左→右,右→左)读取的,因此解密时需要将加密字符串重新拆分成行,并交替方向恢复原始的行内容。
      • 然后按列读取原始消息。
    2. 具体步骤:

      • 给定列数cols和加密字符串s
      • 计算行数rowsrows = len(s) // cols(因为总字母数必须为rows * cols)。
      • s拆分成rows行,每行cols个字符。
        • 第0行:从左到右
        • 第1行:从右到左
        • 第2行:从左到右
        • ...
      • 恢复原始矩形:
        • 对于偶数行(0-based),直接按顺序填充。
        • 对于奇数行(0-based),需要反转后填充。
      • 按列读取原始消息:
        • 从左到右逐列读取,每列从上到下。
    3. 示例解析:

      • 输入:cols = 5, s = "toioynnkpheleaigshareconhtomesnlewx"
      • len(s) = 35, 所以 rows = 35 / 5 = 7
      • 拆分:
        • 第0行:toioy(直接)
        • 第1行:nnkph(反转→ hpkn n)
        • 第2行:eleai(直接)
        • 第3行:gshar(反转→ rahs g)
        • 第4行:econh(直接)
        • 第5行:tomes(反转→ semo t)
        • 第6行:nlewx(直接)
      • 恢复矩形:
        t o i o y  
        h p k n n  
        e l e a i  
        r a h s g  
        e c o n h  
        s e m o t  
        n l e w x  
        
      • 按列读取:
        • 第0列:t, h, e, r, e, s, n → "there sn"
        • 第1列:o, p, l, a, c, e, l → "oplace l"
        • 第2列:i, k, e, h, o, m, e → "ikehome"
        • 第3列:o, n, a, s, n, o, w → "onasnow"
        • 第4列:y, n, i, g, h, t, x → "ynightx"
        • 组合:"theresnoplacelikehomeonasnowynightx"

    代码实现

    while True:
        cols = int(input())
        if cols == 0:
            break
        s = input().strip()
        rows = len(s) // cols
        grid = []
        for i in range(rows):
            start = i * cols
            end = start + cols
            row_str = s[start:end]
            if i % 2 == 1:
                row_str = row_str[::-1]
            grid.append(list(row_str))
        # Read by columns
        original = []
        for c in range(cols):
            for r in range(rows):
                original.append(grid[r][c])
        print(''.join(original))
    

    代码解释

    1. 输入处理:

      • 循环读取输入,直到遇到0为止。
      • 对于每组数据,读取列数cols和加密字符串s
    2. 恢复矩形:

      • 计算行数rows = len(s) // cols
      • 初始化grid作为二维列表存储矩形。
      • s按行拆分,对于奇数行(0-based)进行反转。
    3. 按列读取原始消息:

      • 遍历每一列,从上到下依次读取字符,拼接成原始消息。
    4. 输出:

      • 将拼接后的字符列表转换为字符串并输出。

    示例运行

    输入:

    5
    toioynnkpheleaigshareconhtomesnlewx
    0
    

    输出:

    theresnoplacelikehomeonasnowynightx
    

    注意事项

    • 确保正确处理行方向的交替(偶数行不反转,奇数行反转)。
    • 按列读取时,列优先,行顺序递增。
    • 填充字母是原始消息的一部分,无需特别处理。
    • 1

    信息

    ID
    1040
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者