信息学奥赛一本通_1137_加密的病历单

题目相关

【题目描述】

小英是药学专业大三的学生,暑假期间获得了去医院药房实习的机会。

在药房实习期间,小英扎实的专业基础获得了医生的一致好评,得知小英在计算概论中取得过好成绩后,主任又额外交给她一项任务,解密抗战时期被加密过的一些伤员的名单。

经过研究,小英发现了如下加密规律(括号中是一个“原文 -> 密文”的例子)

1.原文中所有的字符都在字母表中被循环左移了三个位置(dec -> abz)

2.逆序存储(abcd -> dcba )

3.大小写反转(abXY -> ABxy)

【输入】

一个加密的字符串。(长度小于50且只包含大小写字母)

【输出】

输出解密后的字符串。

【输入样例】

GSOOWFASOq

【输出样例】

Trvdizrrvj!

【来源】

1137_加密的病历单

分析

当我们我们已知加密的过程后,若想得到原文,只需对加密后的内容反向处理即可。
加密过程:

  1. 原文中所有的字符都在字母表中被循环左移了三个位置(dec -> abz)
  2. 逆序存储(abcd -> dcba )
  3. 大小写反转(abXY -> ABxy)

那么相对应的解密过程:

  1. 将所有的字符都在字母表中循环右移了三个位置

先解决循环右移,右移不难,将当前位置的赋值给下标+3位置处的即可。

s[i+3]=s[i]

麻烦的地方在于如何进行循环移动。一种方式我们可以进行特判,加上对最后三个位置的字母判断,进行区别处理即可。另一种方式是使用取模符号来模拟循环的效果。

x=(x+1)%k 

这样就能使x在0~ k-1的范围内右移1位进行循环了。我们要对a~z进行循环处理。一共26个英文字母,我们可以对0 ~ 25 进行循环,只要再加上能使’a’ ~ ‘z’ 或 ‘A’ ~ 'Z’对0 ~ 25进行映射对应即可。只需利用ASCII码值,将小写-‘a’ ,将大写-'A’即可产生映射。

if(c是小写){
	c=(c-'a‘+3)%26+'a';
}else if(c是大写){
	c=(c-'A'+3)%26+'A';
}
  1. 逆序存储
    若已知字符串长度len。我们可以找找逆序规律出来
逆序后位置逆序前位置
0len-1
1len-2
2len-3
ilen-i-1

通过列表可找出对应的逆序下标转换规律。

  1. 大小写反转

利用大小写ASCII码值之间的差值为32进行处理。大写的码值小于小写的。所以大写转小写是+32 ,小写转大写是-32。也可以利用cctype中的toupper()和tolower()函数进行转换。

代码实现

#include <iostream>
#include <cstring>
#include <cctype>

using namespace std;
/*
1.大小写反转
2.逆序处理(倒着输出)
3.右移三个位置 
*/
int main()
{
	char s[55]={0},s2[55]={0};
	cin>>s;
	int len=strlen(s);
	for(int i=0;i<len;i++){
		if(isupper(s[i])){
			s[i]=tolower(s[i]);//转成小写
			s[i]=(s[i]-'a'+3)%26+'a';//循环右移3位 
		}else{
			s[i]=toupper(s[i]);//转成大写
			s[i]=(s[i]-'A'+3)%26+'A'; //循环右移3位
		}
	}
	for(int i=0;i<len;i++){//逆置
		s2[i]=s[len-i-1];
	}
	cout<<s2;
	
	return 0;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值