小书童——凯撒密码

GitHub跳转原题关系图返回列表

把每个小写字母转成 0 到 25 的编号,平移 n 位后取模再转回字符。

OJ: luogu

题目 ID: P1914

难度:入门

标签:字符串模拟python

日期: 2026-07-15 20:30

题意

给定一个位移量 n 和一个只含小写字母的字符串。每个字母向后移动 n 位,超过 z 后从 a 继续循环,输出移动后的密码。

思路

把字符看成字母表中的编号:

text
a -> 0, b -> 1, ..., z -> 25

一个字符 ch 平移 n 位后,新编号是:

text
(old + n) % 26

再把新编号加回到 'a' 的 ASCII 编码,就能得到新字符。

这题是字符编码和取模循环练习,不创建 brute.py

Python 知识

  • /home/rainboy/mycode/hugo-blog/content/program_language/python/input_output_and_strings.md:用 input() 读取字符串,用列表收集结果后 "".join(...) 输出。
  • /home/rainboy/mycode/hugo-blog/content/program_language/python/oj_input_output_cheatsheet.md:第一行整数、第二行字符串可以分别读取。
  • ord(ch) 把字符转成编码,chr(x) 把编码转回字符。
  • % 26 表达字母表循环。

代码

python
n = int(input())
s = input().strip()

answer = []
for ch in s:
    offset = (ord(ch) - ord("a") + n) % 26
    answer.append(chr(ord("a") + offset))

print("".join(answer))
cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-07-27 00:00
 * update_at: 2026-07-27 00:00
 */

#include <bits/stdc++.h>
using namespace std;

char s[55]; // 原始密码字符串
int n;      // 位移量

int main() {
    cin >> n >> s;
    int len = strlen(s);
    for (int i = 0; i < len; i++) {
        // 字母编号 0~25,平移 n 位后取模
        int idx = (s[i] - 'a' + n) % 26;
        s[i] = 'a' + idx;
    }
    cout << s;
    return 0;
}

Pythonic 写法

str.maketrans / translate 做凯撒位移:

python
n = int(input())
s = input().strip()
table = str.maketrans(
    {chr(ord("a") + i): chr(ord("a") + (i + n) % 26) for i in range(26)}
)
print(s.translate(table))

复杂度

设字符串长度为 m,时间复杂度是 O(m)O(m),空间复杂度是 O(m)O(m)

总结

凯撒密码的关键是先把字母映射成数字,再用取模处理循环。