E28674:《黑神话:悟空》之加密
implementation, strings, http://cs101.openjudge.cn/pctbook/E28674/
2024年8 月 20 日,广大玩家期待已久的中国首款“3A游戏”《黑神话:悟空》如期发售。游戏内容改编自中国四大名著之一的《西游记》,在正式发布前,游戏已获得业界媒体与评论家们的普遍好评,称赞其在战斗系统、视觉设计以及世界观方面的构建。游戏上线后迅速登顶多个平台的销量榜首,两周内的全球销量超过1800万份,成为有史以来销售速度最快的游戏之一。
你的朋友小xu注意到《黑神话:悟空》至今没有盗版,她感到很好奇,在网上查询后得知《黑神话:悟空》采用“D加密”技术来为防盗版提供技术支持。D加密,全称 Denuvo Anti-Tamper,是由奥地利 Denuvo 公司推出的一种防篡改技术。Denuvo Anti-Tamper 的目标是保护游戏免受盗版和破解攻击。它的原理是在游戏程序中嵌入一些特殊的代码,这些代码会进行复杂的加密和解密操作,使得黑客无法轻易地破解游戏并且在游戏中进行修改。
小xu了解后很感兴趣,于是她开始学习了加密解密相关的技术。某一天,她猜测某一段密文只是采用了一种非常简单的加密方法完成加密:每个字母对应的密文是其在字母表中的后 k 个字母,但 'a' 被视为 'z' 的下一个字母,从而整个字母表形成一个环。例如,如果 k=3,那么字母 'a' 将被加密为 'd','z' 加密为 'c',依此类推。
现在,请你帮助她按照她的猜测完成对密文的破译(即根据密文得出其对应的明文)。
输入
第一行为一个整数 k,表示加密方法中的偏移量。(1 ≤ k ≤ 108000) 第二行为一个由字母组成的字符串 s,表示需要解密的文本。(1 ≤ |s| ≤ 342)
输出
密文对应的明文。
样例输入
sample1 input:
5
LfrjXhnjshj
sample1 output:
GameScience样例输出
sample2 input:
33
IshjrTfaoDbrvun
sample2 output:
BlackMythWukong提示
tags: implementation, strings
来源
2024 TA-lxy
【靳熙恒 25 物理学院】初始化的字母表本来是手打的,学了ASCII码,于是可以自动生成字母表了,解放双手!之后还学到可以用 string 库生成字母表。
characters = [chr(i) for i in range(65, 91)]
uporlow = []
outstring = ''
k = int(input()) % 26
instring = input()
for i in instring:
if i.isupper():
uporlow.append(1)
if i.islower():
uporlow.append(0)
instring = instring.upper()
for i in range(len(instring)):
place = characters.index(instring[i]) - k
if uporlow[i] == 0:
outstring += characters[place].lower()
if uporlow[i] == 1:
outstring += characters[place]
print(outstring)思路:
maketrans是「建规则」:定义 “每个加密字母对应哪个解密字母”;translate是「用规则」:把密文中的字母按规则替换,非字母不变。
import string
k = int(input())
s = input() # 原始密文
# 计算解密偏移(等价于向左移动 k 位)
shift = (-k) % 26
# 原始字母表
lower = string.ascii_lowercase # 'abcdefghijklmnopqrstuvwxyz'
upper = string.ascii_uppercase # 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
# 构建解密后的字母表:每个字母向前移 k 位
decrypted_lower = lower[shift:] + lower[:shift]
decrypted_upper = upper[shift:] + upper[:shift]
# 创建翻译表:将原字母映射到解密后的字母
translation_table = str.maketrans(lower + upper, decrypted_lower + decrypted_upper)
# 应用翻译并输出
print(s.translate(translation_table))def decrypt_caesar_cipher(k, s):
decrypted_text = []
for char in s:
if 'a' <= char <= 'z':
decrypted_char = chr((ord(char) - ord('a') - k) % 26 + ord('a'))
elif 'A' <= char <= 'Z':
decrypted_char = chr((ord(char) - ord('A') - k) % 26 + ord('A'))
else:
decrypted_char = char # Non-alphabetic characters remain unchanged
decrypted_text.append(decrypted_char)
return ''.join(decrypted_text)
# Sample input
k = int(input())
s = input()
# Decrypt and print the result
print(decrypt_caesar_cipher(k, s))Python 取模运算的核心规则
Python 的取模运算
%和整除运算//遵循以下数学关系:被除数 = (被除数 // 除数) * 除数 + (被除数 % 除数)即:
a = (a // b) * b + (a % b)关键在于,Python 的
//运算符执行的是向下取整除法(floor division),也就是结果向负无穷方向取整。计算步骤:
-1 % 26我们按照公式来一步步推导:
计算整除部分
//:-1 // 26
-1除以26等于-0.03846...- 向下取整(向负无穷方向)是
-1。- 所以
-1 // 26 = -1。代入核心公式:
-1 = (-1 // 26) * 26 + (-1 % 26) -1 = (-1) * 26 + (-1 % 26) -1 = -26 + (-1 % 26)求解取模结果:
-1 % 26 = -1 - (-26) -1 % 26 = -1 + 26 -1 % 26 = 25直观理解
你可以把模运算想象成在“钟表”或“循环”上找位置。
- 模
26就像一个有 26 个刻度的圆盘,编号从0到25。- 从
0开始,-1表示向后退一步。- 从
0往后退一步,就会到达25。所以,
-1在模26的系统中,等价于25。为什么这样设计?
这种设计确保了一个非常有用的性质:
当除数(模数)为正数时,取模的结果总是非负的,并且落在
[0, b)的区间内。在这个例子中,
b = 26,所以-1 % 26的结果25落在[0, 26)区间内。这在很多场景下非常有用,例如:
- 数组/列表索引:你想访问一个长度为 26 的列表的最后一个元素,可以用
lst[-1 % 26],它会安全地指向索引25,而不会产生负索引问题(如果直接用-1可能不是你想要的)。- 密码学和数学计算:如凯撒密码中,字母移位后需要回绕到字母表开头,使用正的模结果非常方便。
总结
-1 % 26 = 25是因为:
- Python 的
//是向下取整,-1 // 26 = -1。- 代入公式
-1 = (-1) * 26 + x,解得x = 25。- 结果
25与除数26同号(都为正),并且落在[0, 26)的理想范围内。这是 Python 取模运算的标准且一致的行为。