

第 1 题 如果字符变量 _1 的值是字符 1 ,那么 (int)_1 的值是?( )。
A. 1
B. -1
C. 49
D. +1 或者 -1
【答案】C
【考纲知识点】
字符的 ASCII 编码:C++ 中char类型本质是存储字符对应的 ASCII 码值,将char强转为int时,会返回该字符的 ASCII 十进制值。
字符 '0'的 ASCII 值为 48,因此字符'1'的 ASCII 值为48+1=49。
【解析】
A:错误,'1'的 ASCII 值不是 1,1 是字符代表的数字,不是编码值。
B:错误,无逻辑依据。
C:正确,字符'1'的 ASCII 值为 49,强转int后为 49。
D:错误,ASCII 值固定,不存在正负变化。
第 2 题 a,b是整型变量,各自有互不相同的初始值。下列程序实现了什么效果( )。

A. a,b 的值从始至终都没有改变。
B. a,b 的值实现了互换。
C. a,b 的值互换了以后,又还回去了,相当于没有变化。
D. a,b 的值最后和原值不一样,没有任何意义。
【答案】B
【考纲知识点】
按位异或^运算的性质:
交换律: a ^ b = b ^ a自反性: a ^ a = 0,a ^ 0 = a结合律: (a ^ b) ^ c = a ^ (b ^ c)
【解析】
推导过程
设初始值:a = A,b = B
执行 a = a ^ b→a = A ^ B,b = B执行 b = a ^ b→b = (A ^ B) ^ B = A ^ (B ^ B) = A ^ 0 = A,此时a = A^B,b = A执行 a = a ^ b→a = (A ^ B) ^ A = B ^ (A ^ A) = B ^ 0 = B最终:a = B,b = A,完成了两个变量的无临时变量交换。
A:错误,变量值发生了交换。
B:正确,代码实现了 a、b 的互换。
C:错误,最终值为交换后的值,没有还原。
D:错误,这是经典的无临时变量交换算法,有明确意义。
第 3 题 关于下列正确的程序段,说法正确的是( )。


【答案】C
【考纲知识点】
1、两个数组的本质区别
str1 | "Hello" | {'H','e','l','l','o','\0'} | '\0'(字符串结束标志) | |
str2 | {'H','e','l','l','o'} | {'H','e','l','l','o'} | '\0' |
数组名的本质:C++ 中数组名是指向数组首元素的常量指针,str1 == str2 比较的是两个数组的首地址,而非数组内容。
两个数组是独立的内存空间,因此str1和str2的地址永远不相等,即str1 != str2恒成立。
【解析】
A 选项:错误。str1末尾有'\0',str2没有,数组内容、长度均不同,不是完全相同。
B 选项:错误。cout << str2 << endl 由于没有 '\0' 终止,会一直输出直到遇到内存中的空字符,行为未定义,不一定总是输出不同(可能巧合输出相同,但不可靠),因此B不严谨
C 选项:正确。无论从内容还是地址,两个数组都不相等,描述绝对成立。
str1 由字符串字面量 "Hello" 初始化,实际存储为 {'H','e','l','l','o','\0'},长度6。
str2 由字符列表初始化,存储为 {'H','e','l','l','o'},长度5,无结尾空字符。
因此两个数组大小不同、内容不同,它们不相等
D 选项:错误。两种赋值方式的存储内容、长度均不同,不是完全相同。
字符串自动加\0:双引号初始化自动补结束符,花括号初始化不补,输出时str2会乱码。
第 4 题 关于以下程序段,说法正确的是( )。

A. C++11 标准中,这是未定义行为,不同的环境有可能出现不同的结果
B. 22
C. 21
D. 20
【答案】B
【考纲知识点】
1. 自增运算符的本质
后置自增 x++:先返回x的当前值,再将x自增 1
前置自增 ++x:先将x自增 1,再返回x的新值
2. 求值顺序的关键说明
C++17 之前(含 C++11):+运算符的左右操作数没有规定求值顺序,属于未定义行为 (UB),编译器可以自由选择先算左操作数、先算右操作数,甚至交错执行,因此结果不固定。
部分编译器(如 GCC、MSVC 的默认实现):会采用 「从右到左」求值 的顺序,这是最常见的实现,此时会得到22的结果,这也是很多教材 / 考试中默认的计算逻辑。
【解析】
「从右到左」求值的计算过程(得到 22 的推导)
(1)初始值:x = 10
(2)先计算右操作数 ++x:
前置自增,x先加 1 → x = 11,返回11
(3)再计算左操作数 x++:
后置自增,返回x的当前值11,然后x加 1 → x = 12
(4)计算加法:11 + 11 = 22,最终输出22
其他求值顺序的可能结果(说明未定义行为)
「从左到右」求值(部分编译器 / 优化下的结果)
(1)初始值:x = 10
(2)先算左操作数x++:返回10,x变为11
(3)再算右操作数++x:x变为12,返回12
(4)加法:10 + 12 = 22(巧合结果相同)
注:部分编译器会得到21,是因为求值顺序的交错优化,属于未定义行为的正常表现。
A 选项:从 C++ 标准的严谨角度,该表达式在 C++11 中是未定义行为,这是标准层面的正确结论。尽管 C++ 标准中此类表达式属于未定义行为,但在大多数常见编译器(如 GCC、MSVC 未开启严格警告时)实际运行结果为 22。
B 选项:在绝大多数编译器的默认实现(从右到左求值)下,输出结果为22,是考试 / 编程实践中最常见的结果,因此很多题目会将 B 作为正确答案。
C/D 选项:仅在特定编译器 / 优化下可能出现,不是主流结果。
第 5 题 8 位二进制下,十进制数-15 的补码是( )。
A. 11110000
B. 10001111
C. 10010000
D. 11110001
【答案】D
【考纲知识点】
补码的计算规则(8 位带符号整数)
1、正数:原码 = 反码 = 补码,符号位为 0
2、负数:补码 = 原码除符号位取反 + 1
步骤:
(1)求 15 的 8 位原码:00001111
(2)求 - 15 的原码:符号位变 1 → 10001111
(3)求反码:除符号位取反 → 11110000
(4)补码:反码 + 1 → 11110001
【解析】
A:11110000是 - 15 的反码,不是补码,错误。
B:10001111是 - 15 的原码,错误。
C:10010000无对应关系,错误。
D:11110001是 - 15 的补码,正确。

A. 63
B. 65
C. 67
D. 69
【答案】B
【考纲知识点】
r 进制转十进制的按权展开法
公式:对于 r 进制数 dₙdₙ₋₁...d₁d₀,十进制值 =dₙ×rⁿ + dₙ₋₁×rⁿ⁻¹ + ... + d₁×r¹ + d₀×r⁰
【解析】
计算过程
三进制数2102,从右到左权值为3⁰, 3¹, 3², 3³:

第 7 题 二进制数 10110101 是某数的 8 位补码,该数的十进制是( )。
A. -73
B. -75
C. -77
D. 75
【答案】B
【考纲知识点】
补码转十进制(8 位带符号整数)
(1)补码最高位为符号位: 0表示正数,1表示负数(2)正数:补码直接转十进制 (3)负数:补码 → 原码(补码除符号位取反 + 1) → 十进制
【解析】
计算过程
补码10110101,符号位为1,是负数:
除符号位取反: 11001010加 1 得到原码: 11001011原码转十进制:符号位 1表示负,数值部分1001011

因此该数为-75
补码计算:负数补码 = 反码 + 1,补码转负数 = 取反 + 1 加负号
【总结】
负数补码 → 原码的两种方法(8 位)
已知:补码 = 10110101(对应 -75)
方法①:补码 减 1 → 再按位取反(符号位不变)
(1)补码: 1011 0101(2)减 1: 1011 0100(3)符号位不动,其余取反: 1100 1011→ 原码
方法②:补码 除符号位取反 → 再 +1
(1)补码: 1011 0101(2)符号位不动,其余取反: 1100 1010(3)加 1: 1100 1011→ 原码
第 8 题 已知 unsigned char c = 0x0F; (十六进制 0F = 二进制 00001111 ),执行 c = c << 3; 后, c 的十进制值是:( )。
A. 64
B. 72
C. 80
D. 120
【答案】D
【考纲知识点】
左移运算符 <<:
(1)无符号数左移 n位,等价于乘以 2ⁿ,高位溢出丢弃,低位补 0。(2)unsigned char是 8 位无符号整数,范围 0~255。
【解析】
计算过程
初始值: 0x0F= 二进制0000 1111= 十进制15左移 3 位: 0000 1111 << 3=0111 1000二进制 01111000转十进制:64+8+4+2+0=120左移运算:无符号数左移 n 位 = 乘2ⁿ,高位丢弃,低位补 0
第 9 题 补码的情况下,关于按位取反运算,用笔计算的情况下,以下说法错误的是:( )
A. ~5 的结果是 -6( int 类型,32 位)
B. ~0 的结果是 0( int 类型,32 位)
C. ~(-3) 的结果是 2( int 类型,32 位)
D. ~8 的结果是 -9( int 类型,32 位)
【答案】B
【考纲知识点】
按位取反 ~ 运算规律:对于任意整数 x,有公式:~x = -x - 1(32 位补码系统中恒成立)
原理:补码按位取反后,等于原数的相反数减 1。
【解析】
A 选项:~5 = -5 -1 = -6 ✅ 正确
B 选项:~0 = -0 -1 = -1,不是 0 ❌ 错误
C 选项:~(-3) = -(-3) -1 = 3 -1 = 2 ✅ 正确
D 选项:~8 = -8 -1 = -9 ✅ 正确
~x = -x - 1,直接秒算结果第 10 题 执行以下 C++ 代码后, sub 的值是( )。

A. 20
B. 02
C. 2026
D. 026
【答案】A
【考纲知识点】
string::substr(pos, len) 函数:
pos:从 0 开始计数的起始下标
len:截取的字符长度
功能:从字符串的 pos 位置开始,截取 len 个字符。
【解析】
字符串下标拆解
str = "GESP2026",下标从 0 开始:
substr(4, 2):从下标 4 开始,截取 2 个字符 → 字符2(下标 4)、0(下标 5)
最终 sub = "20"
substr 函数:下标从 0 开始,第一个参数是起始位置,第二个是截取长度
第 11 题 执行以下代码后,输出结果是:( )。

A. 4
B. 6
C. 24
D. 30
【答案】B
【考纲知识点】
sizeof运算符计算数组长度
sizeof(arr):返回整个数组占用的总字节数
sizeof(arr[0]):返回数组单个元素占用的字节数
数组长度 = 总字节数 ÷ 单个元素字节数
【解析】
计算过程
数组arr有 6 个int元素,int占 4 字节
sizeof(arr) = 6 × 4 = 24
sizeof(arr[0]) = 4
count = 24 / 4 = 6
数组长度计算:sizeof(数组) / sizeof(数组[0]) 是通用公式,适用于所有基础类型数组
第 12 题 执行以下代码后,输出结果是:( )。

A. 4
B. 5
C. 6
D. 10
【答案】B
【考纲知识点】
sizeof与strlen的区别
sizeof(s):返回数组s的总字节数(数组定义长度为 10,因此总字节数为 10)
sizeof(s[0]):单个char占 1 字节,因此a = 10 / 1 = 10
strlen(s):返回字符串的有效长度(不含末尾'\0'),"abcde"长度为 5,因此b = 5
【解析】a - b = 10 - 5 = 5
sizeof vs strlen:sizeof算数组总长度,strlen算字符串有效长度(不含'\0')
第 13 题 以下问题中,最不适合用枚举法解决的是:( )
A. 找出 1~100 之间所有能被 7 整除的数
B. 找出 100~200 之间的所有质数
C. 计算 1+2+3+…+1000 的和
D. 找出三位数中个位、十位、百位数字之和等于 10 的数
【答案】C
【考纲知识点】
枚举法:逐一遍历所有可能的情况,判断是否满足条件,适合数据范围小、遍历成本低的问题
不适合枚举的场景:有明确数学公式、可直接计算的问题(枚举会做无用功,效率极低)
【解析】
A 选项:1~100 范围小,可枚举遍历,适合枚举
B 选项:100~200 范围小,可枚举判断质数,适合枚举
C 选项:有明确的求和公式 S = n(n+1)/2,直接计算即可,完全不需要枚举,最不适合用枚举法
D 选项:三位数共 900 个,范围小,可枚举遍历,适合枚举
枚举法适用场景:范围小、无公式、需逐一判断的问题;有公式的问题优先用公式,不枚举
第 14 题 用枚举法解决 “鸡兔同笼问题:头共 35 个,脚共 94 只,求鸡和兔的数量”,以下枚举逻辑最合理的是:()
A. 枚举鸡的数量 x (0~35),兔的数量 y=35-x ,判断 2*x + 4*y == 94
B. 枚举兔的数量 y (0~94),鸡的数量 x=35-y ,判断 2*x + 4*y == 94
C. 枚举所有整数 x (0-100)和 y (0-100),判断 x+y==35 && 2*x+4*y==94
D. 枚举脚的总数 sum (0~94),判断 sum == 94
【答案】A
【考纲知识点】
枚举法的核心是减少无效遍历、缩小枚举范围,利用已知条件减少枚举次数,提升效率。
鸡兔同笼的核心约束:
(1)总头数 = 鸡数 + 兔数 = 35 → 兔数 = 35 - 鸡数,无需同时枚举两个变量
(2)鸡有 2 只脚,兔有 4 只脚 → 总脚数 = 2× 鸡数 + 4× 兔数
【解析】
A 选项:✅ 最合理。
仅枚举鸡的数量 x(范围 0~35,仅 36 次遍历),兔数由总头数直接算出,无冗余计算,效率最高,逻辑最严谨。
B 选项:❌ 不合理。
枚举兔的数量 y 的范围错误(兔数最多 35 只,而非 0~94),范围过大,存在无效遍历。
C 选项:❌ 不合理。
双重枚举 x 和 y,遍历次数达 101×101=10201 次,存在大量无效计算,完全浪费,不是最优逻辑。
D 选项:❌ 完全错误。
仅枚举脚的总数,无法区分鸡和兔的数量,无法解决问题。
第 15 题 模拟 “字符串加密”:规则为 “每个字符 ASCII 码 + 3,若超过 z (122) 则从 a 重新开始”,以下代码中正确的条件判断是:( )

A. if (str[i]> 122) str[i] = str[i] + 3 - 26;
B. if (str[i] > 122) str[i] = str[i] - 26;
C. if (str[i] + 3 > 122) str[i] = str[i] - 23;
D. if (str[i] + 3 > 'z') str[i] = 'a' + (str[i] + 3 - 'z') - 1;
【答案】D
【考纲知识点】
字符加密的循环逻辑:
1、小写字母a的 ASCII 码为 97,z为 122,共 26 个字母。
2、加密规则:字符 + 3,若超过z(122),则绕回a重新开始,等价于:
若原字符+3 > 122,则新字符 = a + (原字符+3 - z - 1)(或等价的原字符+3-26)
【解析】
A 选项:❌ 错误。
判断条件错误:判断的是原字符+3>122,而非原字符>122,逻辑完全错误。
B 选项:❌ 错误。
判断条件错误(同 A),且赋值逻辑错误,无法正确绕回。
C 选项:❌ 错误。
str[i] -23 等价于 str[i]+3-26,赋值逻辑正确,但判断条件str[i]+3>122的写法不直观,且与 D 选项的可读性、严谨性相比,不是最优。
D 选项:✅ 正确。
1、判断条件if (str[i] + 3 > 'z'):用字符常量'z'替代 122,可读性强,逻辑严谨。
2、赋值逻辑'a' + (str[i] + 3 - 'z') - 1:
(1)计算原字符+3超过z的偏移量,绕回a,完全符合规则。
(2)例如:y(121)+3=124>122 → 'a' + (124-122)-1 = 97 +2-1=98 → b,正确。
(3)z(122)+3=125>122 → 'a' + (125-122)-1=97+3-1=99 → c,正确。字符加密循环:判断原字符+3 > 'z',绕回a的公式:'a' + (原字符+3 - 'z') - 1。

第 1 题 定义 int arr[5] = {1,2,3}; ,则 arr[3] 的值为 0, arr[5] 是合法下标。
【答案】×
【考纲知识点】数组的定义与下标访问
【解析】
1、不完全初始化:当数组初始化元素个数少于定义长度时,剩余元素自动初始化为 0。
arr[5] 包含 5 个元素:{1, 2, 3, 0, 0},所以 arr[3] = 0 ✅。
2、下标范围:数组下标从 0 开始,长度为 n 的数组,合法下标范围是 0 到 n-1。
本题数组长度为 5,合法下标为 0~4,arr[5] 越界 ❌。
第 2 题 定义 double arr[10]; ,未手动初始化时,数组中所有元素的默认值为 0.0。
【答案】×
【考纲知识点】局部数组 vs 全局 / 静态数组
【解析】
- 局部数组
(函数内定义):未初始化时,内容是随机的垃圾值,不是 0。 - 全局数组
或 静态数组( static修饰):未初始化时,自动初始化为 0。
题目未说明作用域,默认按局部数组处理,因此默认值不是 0.0。
第 3 题 定义 int arr[] = {1,2,3}; ,则 sizeof(arr) 的结果为 12( int 占 4 字节)。
【答案】√
【考纲知识点】sizeof 计算数组大小
【解析】
arr[] = {1,2,3} 表示长度为 3 的数组。
sizeof(arr) = 元素个数 × 单个元素大小 = 3 × 4 = 12 字节。
第 4 题 下面的流程图是用来求 1+2+3+…+10 的和。
请判断:这个流程图的逻辑正确还是错误?

【答案】√
【考纲知识点】循环结构逻辑(for/while 等价)
【解析】
流程图逻辑:
开始 sum=0, i=1。判断 i <= 10:是:执行 sum = sum + i→i = i + 1→ 回到判断。否:输出 sum。
第 5 题 下面流程图的功能是计算 5 对 2 取余数,输出结果为 1。

【答案】√
【考纲知识点】流程图的执行流程(辗转相减逻辑)
【解析】
流程图逻辑:
初始化 a=5, b=2。判断 a >= b:是: a = a - b(5-2=3) → 回到判断。否:输出 a。
执行过程:
初始 a=5, b=2。5 >= 2 → a=3。3 >= 2 → a=1。1 < 2 → 输出 1。结果为 1,与 5%2=1 一致。
第 6 题 已知大写字符 A 的ASCII编码的十六进制表示为 0x41 ,计算字符 m 的ASCII编码的八进制表示为 155(八进制)。
【答案】√
【考纲知识点】进制转换与字符编码
【解析】八进制 155 转十进制:

十进制 109 对应的 ASCII 字符就是 'm'。
第 7 题 在 C++ 位运算中,各种不同的运算符有优先级的区分,使用括号能够解决优先级的问题。
【答案】√
【考纲知识点】运算符优先级与结合性
【解析】
括号 () 的优先级最高,使用括号可以强制改变运算顺序,消除优先级歧义。
例如:a + b * c 默认先乘后加,(a + b) * c 先加后乘。
第 8 题 由于在 0~255 范围内, char 类型和 int 类型可以互换,因此在这里 x 和 y 相等。

【答案】×
【考纲知识点】类型本质与隐式转换
【解析】
char x='1':存储的是字符 '1' 的 ASCII 码值,即 49。
int y=1:存储的是整数 1。
虽然 char 在 0~255 范围内可以与 int 互换存储,但值并不相等(49 ≠ 1)。
第 9 题 在C++语言中,表达式 ((0xf0 + 0x15) == 255) 的值为 true 。
【答案】×
【考纲知识点】十六进制加法与进制转换
【解析】
1、十六进制转十进制:
0xf0 = 15×16 + 0 = 240
0x15 = 1×16 + 5 = 21
2、相加:240 + 21 = 261。
3、比较:261 ≠ 255。
第 10 题 如果 a 为 int 类型的变量,且 a 的二进制最低位为 0 ,则表达式 ((a & 3 & 1) == 0) 的值为true 。
【答案】√
【考纲知识点】位运算(按位与 &)
【解析】
1、最低位为 0 → 表示 a 是偶数。
2、a & 1:用于判断最低位。结果为 0 说明最低位是 0。
3、运算优先级:& 优先级高于 ==,但结合性为从左到右。
(1)a & 3 & 1 = (a & 3) & 1。
(2)因为 a 最低位为 0,所以 a & 1 结果必为 0,整个表达式值为 true。
3.1 编程题 1
试题名称:二进制回文串
时间限制:1.0 s
内存限制:512.0 MB
3.1.1题目描述

【考纲知识点】
1、进制转换:将十进制数转换为二进制字符串
2、回文数判断:验证字符串正序与逆序是否完全一致
3、枚举法:遍历指定范围,筛选符合条件的数
【解题思路】
采用暴力枚举法最直观且符合数据范围要求(n≤105,最大循环 10 万次,效率完全足够)。
算法步骤:
1、输入数据:读取正整数 n
2、初始化计数器:count = 0
3、遍历区间:从 1 到 n 逐个检查
4、二进制转换:将每个数转为不含前导零的二进制字符串
5、回文判断:比较字符串与反转后的字符串是否相等
6、统计结果:符合条件的数计数器加 1
7、输出结果:打印最终计数器值
【参考程序1】(用字符串存二进制)
#include<iostream>#include<string>#include<algorithm>using namespace std;// 十进制转二进制字符串string toBinary(int n){if (n == 0) return "0";string res;while (n > 0) {res += (n % 2) ? '1' : '0';n /= 2;}reverse(res.begin(), res.end());return res;}// 判断回文boolisPalindrome(const string& s){int l = 0, r = s.size() - 1;while (l < r) {if (s[l] != s[r]) return false;l++; r--;}return true;}intmain(){int n;cin >> n;int cnt = 0;for (int i = 1; i <= n; ++i) {string bin = toBinary(i);if (isPalindrome(bin)) {cnt++;}}cout << cnt << endl;return 0;}
reverse(res.begin(), res.end()); 的作用因为算二进制的时候,算出来是反的!
比如数字 5 → 二进制应该是 101
但我们用 %2/2 算出来的顺序是:先得到最低位 1 → 然后 0 → 然后最高位 1所以算出来是 101 倒着存的 → "101"
刚好这题是回文,所以结果一样,但原理必须懂。
二进制转换的反转:必须保留(因为%2//2法生成的是逆序,不反转就不是正确的二进制。得到的是逆序二进制,回文判断会出错)
比如数字 6(二进制110):
计算:6%2=0 → res="0",6/2=3
3%2=1 → res="01",3/2=1
1%2=1 → res="011"
此时 res 是 "011",是反的,正常二进制是110,所以必须反转成"110"
【参考程序2】(用数组存二进制)
#include<iostream>using namespace std;intmain(){int n, a[50] = {0}, ans = 0;cin >> n;for (int i = 1; i <= n; i++) {int t = i;int pos = 0;// 1. 转二进制,低位存在前while (t) {a[pos++] = t % 2;t /= 2;}// 2. 判断回文 (核心逻辑未变)bool is_pal = true;// 只需循环一半长度,减少比较次数for (int j = 0; j < pos / 2; j++) {if (a[j] != a[pos - 1 - j]) {is_pal = false;break; // 只要有一个不等,直接退出}}if (is_pal) ans++;}cout << ans << endl;return 0;}
1. 二进制转换(存的是逆序,但刚好能用)
原理:比如 t = 6 (110)
第一次循环:6%2=0 → a[0] = 0 (对应二进制最低位)
第二次循环:3%2=1 → a[1] = 1
第三次循环:1%2=1 → a[2] = 1 (对应二进制最高位)
结果:数组里存的是 a = [0, 1, 1]。
注意:这和正常二进制 110 是逆序的。
这里转二进制不用反转。
3.2 编程题 2
试题名称:凯撒密码
时间限制:1.0 s
内存限制:512.0 MB
3.2.1 题目描述
凯撒密码是一种替换加密技术,明文中的所有字母都在字母表上向后(或向前)按照一个固定数目进行偏移后被替换成密文。例如,当偏移量是 3的时候,所有的字母A 将被替换成D , B被替换成E ,C 被替换成 F,以此类推,W被替换成Z ,X 被替换成 A, Y被替换成B , Z被替换成 C。这个加密方法是以罗马共和时期凯撒的名字命名的,据称当年凯撒曾用此方法与其将军们进行联系。
但是和所有的利用字母表进行替换的加密技术一样,凯撒密码非常容易被破解,而且在实际应用中也无法保证通信安全。
现在给你一个已破解的凯撒密码明文与密文,与一个有相同偏移量的未破解凯撒密码密文,请你帮忙破解它。
3.2.2 输入格式
输入共三行:
第一行包含一个字符串,表示已破解的凯撒密码明文;
第二行包含一个字符串,表示已破解的凯撒密码密文;
第三行包含一个字符串,表示待破解的凯撒密码密文。
3.2.3 输出格式
输出一行,包含一个字符串,表示待破解的凯撒密码对应的明文。

【考纲知识点】
1、ASCII 码运算:利用字符的 ASCII 码数值差计算偏移量。
(1)大写字母 A-Z 的 ASCII 码范围是 65-90。
(2)偏移量 key = 密文字符 - 明文字符(取模处理循环)。
2、模运算(%):处理字母表的循环特性(如 W 偏移 3 变 Z,X 偏移 3 变 A)。
公式:(c - 'A' + 26) % 26 确保结果在 0-25 之间,避免负数。
3、字符映射:根据偏移量,对目标密文逐字符进行逆向偏移。
【解题思路】
1、计算偏移量 key:
(1)输入已知的明文 s1 和密文 s2。
(2)取第一个字符(或任意对应位置字符)计算:key = (s2[0] - s1[0] + 26) % 26。
(3)原理:偏移量是固定的,key = 密文 - 明文。
2、破解目标密文:
(1)输入待破解的密文 s3。
(2)遍历 s3 的每个字符 c:
(3)计算公式:明文 = (c - 'A' - key + 26) % 26 + 'A'。
(4)加 26 再取模是为了防止负数(例如 c='A',key=3,0-3=-3,加 26 得 23,模 26 仍为 23,对应 X)。
3、输出结果:拼接所有解密后的字符并输出。
【参考程序】
#include<iostream>#include<string>using namespace std;intmain(){string plain, cipher, target;// 1. 读取输入cin >> plain >> cipher >> target;// 2. 计算偏移量 key (D'-'A' = 3)int key = (cipher[0] - plain[0] + 26) % 26;// 3. 逐字符解密并输出for (char c : target) {// 核心公式:(当前字符 - 基准 - 偏移 + 26) % 26 + 基准int decrypted = (c - 'A' - key + 26) % 26 + 'A';cout << (char)decrypted;}cout << endl;return 0;}
【易错点避坑】
1、负数处理:必须在计算时加 26 再取模,否则会出现负数导致错误(如 'A' - 1 会变成乱码)。
2、大小写混淆:题目保证全大写,无需处理小写。
3、偏移方向:题目要求逆向解密,必须用 (c - key),而不是 (c + key)。

