GESP三级

一. 凯撒密码

题目描述

凯撒密码是一种替换加密技术,明文中的所有字母都在字母表上向后(或向前)按照一个固定数目进行偏移后被替换成密文。例如,当偏移量是 333 的时候,所有的字母 AAA 将被替换成 DDDBBB 被替换成 EEECCC 被替换成 FFF,以此类推,WWW 被替换成 ZZZXXX 被替换成 AAAYYY 被替换成 BBBZZZ 被替换成 CCC。这个加密方法是以罗马共和时期凯撒的名字命名的,据称当年凯撒曾用此方法与其将军们进行联系。

但是和所有的利用字母表进行替换的加密技术一样,凯撒密码非常容易被破解,而且在实际应用中也无法保证通信安全。

现在给你一个已破解的凯撒密码明文与密文,与一个有相同偏移量的未破解凯撒密码密文,请你帮忙破解它。

输入格式

输入共三行:

第一行包含一个字符串,表示已破解的凯撒密码明文;

第二行包含一个字符串,表示已破解的凯撒密码密文;

第三行包含一个字符串,表示待破解的凯撒密码密文。

输出格式

输出一行,包含一个字符串,表示待破解的凯撒密码对应的明文。

输入输出样例 #1

输入 #1

ABCDEFGVWXYZ
DEFGHIJYZABC
WKHTXLFNEURZQIRAMXPSVRYHUWKHODCBGRJ

输出 #1

THEQUICKBROWNFOXJUMPSOVERTHELAZYDOG

说明/提示

样例解释

样例 1 中,通过已破解的密码得出偏移量为 'D' - 'A' = 3,因此,对未破解部分进行逆向偏移:密文中的 W 对应明文中的 T'W' - 3 = 'T'),密文中的 K 对应明文中的 H'K' - 3 = 'H'),以此类推。

数据范围

保证密码长度均不超过 100010001000,所有字符串由大写字母组成。


解:

思路如下

  1. 确定偏移规则:通过已破解的明文和密文,计算出统一的偏移量(例如第一个字符的差值)。由于转换规则一致,只需根据第一个字符确定偏移方向与大小。
  2. 处理边界情况:当偏移后超出字母范围时,需要进行循环处理(如 ‘A’ 向左偏移变为 ‘Z’)。
  3. 解密待破解密文:对密文中的每个字符应用逆向偏移,得到对应的明文。
#include<bits/stdc++.h>
using namespace std;

int main(){

    string s1, s2, s;         // s1明文,s2密文,s待翻译的密文
    string ans = "";         // 转换后的字符串
    cin >> s1 >> s2 >> s;
    int n = s2[0] - s1[0];   // 找出转换规律
    for(int i = 0; i < s.size(); i++){
        char a = s[i] - n;   // 按规则进行转换
        if(a < 'A'){         // 超出字母表范围,循环回末尾
            a += 26;
        }else if(a > 'Z'){  // 超出字母表范围,循环回开头
            a -= 26;
        }
        ans += a;
    }
    cout << ans;
    return 0;
}

优化提示:也可以直接使用数学公式 (s[i] - 'A' - n + 26) % 26 + 'A' 来统一处理偏移与循环,避免分类讨论。如果赛时无法快速推导正确公式,建议使用分类讨论规则写法。


二. 二进制回文串

题目描述

对于一个正整数 nnn,我们将其转换为不含前导零的二进制表示,如果这个二进制序列从左向右读与从右向左读完全相同,则称该数为二进制回文数。例如,999 的二进制表示为 (1001)2(1001)_2(1001)2,是二进制回文数;121212 的二进制表示为 (1100)2(1100)_2(1100)2,不是二进制回文数。

你的任务是:给定一个正整数 nnn,计算在 111nnn 的范围内二进制回文数的数量。

输入格式

输入一行,包含一个正整数 nnn

输出格式

输出一行,包含一个数,表示在 111nnn 的范围内二进制回文数的数量。

输入输出样例 #1

输入 #1

15

输出 #1

6

说明/提示

样例解释

样例 1 中,111151515 范围内 111333555777999151515 是二进制回文数。

数据范围

1≤n≤1051 \leq n \leq 10^51n105

解法1(数字分解法)

思路

  1. 枚举 iii111nnn
  2. iii 转换为二进制数(用十进制形式存储,如 4→1004 \to 1004100)。
  3. 判断该二进制数是否为回文数(反转后是否与原数相等)。

⚠️注意: 注意:n≤105n \leq 10^5n105 时,二进制表示最多 171717 位,需使用 long long 存储。

#include<bits/stdc++.h>
using namespace std;
bool check(int x) {
    long long x_to_2 = 0;   // 转换为二进制
    long long p = 1;        // 10的幂
    while(x) {
        x_to_2 += x % 2 * p;
        x /= 2;
        p *= 10;
    }
    long long x_to_2_tmp = x_to_2;
    long long rev = 0;     // x_to_2的反转数字
    while(x_to_2_tmp) {
        rev = rev * 10 + x_to_2_tmp % 10;
        x_to_2_tmp /= 10;
    }
    return rev == x_to_2;
}
int main(){
    int n, ans = 0;
    cin >> n;
    for(int i = 1; i <= n; i++){
        if(check(i)) ++ans;
    }
    cout << ans << endl;
    return 0;
}

解法2(数组,字符串)

思路

  1. 枚举iii1−n1 - n1n
  2. iii先转换为二进制对应的字符串s, 然后判断s是否为回文串即可。
#include<bits/stdc++.h>
using namespace std;
bool check(int x) {
    string s = "";    // 二进制字符串初始化
    while(x) {
        s += (x % 2) + '0';   //单数字 + '0' 转化为数字字符
        x /= 2;
    }
    for (int i = 0; i < s.size() / 2; i++) {  //枚举字符串(一半即可)
        //  依次判断s[0] = s[s.size() - 1]
        //         s[1] = s[s.size() - 2]
        //         ...
        if (s[i] != s[s.size() - 1 - i])
            return false;
    }
    return true;
}
int main(){
    int n, ans = 0;
    cin >> n;
    for(int i = 1; i <= n; i++){
        if(check(i)) ++ans;
    }
    cout << ans << endl;
    return 0;
}
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐