本题要求根据加密规则,还原出加密前的整数。加密规则如下:
a 为 1,b 为 2,……,z 为 26);'A' 的 ASCII 码为 65,代表 -65)。题目给定一个长度为 n 的字符串 T,其中仅包含大小写字母。需要求出字符串中所有字母对应数值的总和,并输出这个整数。
数据规模 n ≤ 10^5,保证答案可以用普通的 int 存储(最大范围为 -90×10^5 到 26×10^5,在 int 可表示范围内)。
这是一道简单的模拟题。核心任务是对字符串中的每个字符进行判断,根据字符的类型累加或累减对应的数值:
ans = 0。ch:
ch 是小写字母('a' ≤ ch ≤ 'z'),则累加 (ch - 'a' + 1);ch 是大写字母('A' ≤ ch ≤ 'Z'),则累减 ch(相当于加上 -ch),这里的 ch 在运算时会被自动转换为对应的 ASCII 码整数值。ans。由于大小写字母在 ASCII 表中是连续分布的,因此上述判断和计算可以直接利用字符的 ASCII 码完成,无需建立映射表。
算法只需要一次线性遍历:
ch - 'a' 可以得到字母在 0~25 之间的偏移量,再加 1 即为其代表的数值。'A')到 90('Z'),其相反数就是 -ch,代码中直接执行 ans -= ch 即可,因为 ch 作为整型参与运算时会隐式转换为 ASCII 码值。比如样例 aAc:
'a':小写,累加 'a' - 'a' + 1 = 1'A':大写,累减 'A' 即减去 65,等价于累加 -65'c':小写,累加 'c' - 'a' + 1 = 31 - 65 + 3 = -61。题目保证字符串中的字符只有大写或小写字母,所以不需要考虑其他字符。参考代码中的 assert 语句用于在调试阶段确保字符串长度与输入的 n 一致,同时检查是否存在非法字符,可以在竞赛环境下帮助快速发现错误,但最终提交时一般不会影响正确性。
整个算法只对字符串进行了一次从左到右的遍历,每次循环内部只进行常数次判断和加减运算,因此时间复杂度为 O(n),其中 n 是字符串的长度。
空间复杂度为 O(n)(用于存储输入字符串),如果采用单个字符边读边处理的方式可以优化到 O(1),但就本题数据规模而言,直接使用字符数组完全没有问题。
cpp1#include <iostream> 2#include <cstring> // 为了 strlen 3#include <cstdio> 4#include <cstdlib> 5#include <assert.h> 6using namespace std; 7 8const int N = 100005; // 字符串最大长度 9char str[N]; 10 11int main() { 12 int n; 13 cin >> n; 14 cin >> str; // 读入字符串 15 assert(n == strlen(str)); // 确保输入长度正确(调试用) 16 17 int ans = 0; 18 for (int i = 0; i < n; i++) { 19 if (str[i] >= 'a' && str[i] <= 'z') // 小写字母 20 ans += str[i] - 'a' + 1; 21 else if (str[i] >= 'A' && str[i] <= 'Z') // 大写字母 22 ans -= str[i]; // 等价于 ans += -str[i] 23 else 24 assert(false); // 如果出现非法字符,在调试时会报错 25 } 26 27 cout << ans << endl; 28 return 0; 29}
代码说明:
str 数组开辟了足够空间来存储最长字符串。cin >> str 读取字符串,遇到空白字符停止,因此适合题目中“由大写字母和小写字母组成”的输入。if-else 判断是小写还是大写字母,并做相应累加。对于小写字母,str[i] - 'a' + 1 精确计算出位置;对于大写字母,直接 ans -= str[i],利用了字符型与整型之间的隐式转换,减去的是该大写字母的 ASCII 码值,符合题目要求的相反数。assert(false) 用于捕获非法输入,保证程序在不符合假设时立即终止,是竞赛编程中常见的安全手段。这道题考察了对字符 ASCII 码和基本循环控制的掌握,代码实现直观清晰,非常适合于入门模拟练习。