题目描述
题目内容:
A国情报局抓获敌国间谍一名,从间谍身上搜出了若干密电,在严刑逼供之下,间谍说出了密电加密方法:将明文电报(仅由大写字母构成)中的所有字母均替换为字母表中向后看的第n个字母,如果超过Z,则从A继续数,这样就得到了密文,比如ATTACK,向后看第2个字母,就加密为CVVCFM。
可还没等到间谍说出加密用的密钥(数字n),就被卧底开枪打死,间谍临死前在地板上画了BYE三个字母。
情报局长看着一条条密电发了愁,但机智的你已经发现,原来间谍在告诉我们,所有密电的明文都以BYE结尾!
请编写程序破译这些密电吧!
输入格式:
共一行字符串,全部由大写字母构成的密文。
输出格式:
共一行字符串,破译后的明文。
输入样例1:
JNTQZCZF
输出样例1:
IMSPYBYE
时间限制:500ms内存限制:32000kb
解题思路
原始思路
- 所有密电明文均以BYE结尾,因此我们可以利用该条件获知密钥n。(通过密文的最后三位字母中的任意一个均可获取,n即为对应位置的字母编码值的差值)
- 如果明文超过“Z”,则从“A”继续数,这里我们可以借助其与26的差值得到。(英文字母总个数为26)
- 将密文和明文分为两部分,最后三位和其他部分,分别计算即可
a = input().upper()
b = ""
n = ord('E')-ord(a[-1])
for i in a[:-3]:
if ord(i)+n>ord("Z"):
b += chr(ord(i)+n-26)
else:
b += chr(ord(i)+n)
b += "BYE"
print(b)
思路缺陷
在第一步中考虑不周,忽视了n的取值范围。举例说明,若a[-1]=“Z”,则n=-21,那么当ord(i)=65,即i="a"时,chr的值就已不是任何一个大写字母
思路改进
将n的取值分情况讨论,计算出n的精确值
换种想法
对于具有周期性的数列,取余数不失为一种好方法
- 生成一个包含26个字母并且顺序排列的列表,或可简称为字母表(`・ω・´)
- 按照题目要求,先求出密钥n
- 利用密钥n求解密文移动后的位置,利用余数求解明文( 划重点 :由于此前已经生成新的字母表,范围在在[0,25]内,所以此时利用生成后的位置数对26(字母个数)取余极为方便)
解题代码
思路一
a = input().upper()
b = ""
if a[-1]<='E':
n = ord('E')-ord(a[-1])
else:
n = 26+(ord('E')-ord(a[-1]))
for i in a[:-3]:
if ord(i)+n>ord("Z"):
b += chr(ord(i)+n-26)
else:
b += chr(ord(i)+n)
b += "BYE"
print(b)
思路二
a = input().upper()
l = [chr(i) for i in range(ord("A"),ord("Z")+1)]
n = l.index('E')-l.index(s[-1])
b = ""
for i in a[:-3]:
b += l[(l.index(i) + n)%26]
b += "BYE"
print(b)