题解:学而思编程 数字加密
【题目来源】
学而思编程:数字加密
【题目描述】
对一个十进制的四位数来说,我们可以用以下过程将它加密成另一个四位数:
首先,将个位和千位对调;
然后,将十位和百位对调;
最后每位 \(0\) 换成 \(9\),每位 \(1\) 换成 \(8\),每位 \(2\) 换成 \(7\),\(\ldots\),每位 \(9\) 换成 \(0\)。
例如,对 \(8429\) 加密,则
个位和千位对调后得 \(9428\);
十位和百位对调后得 \(9248\);
将每个数字替换后得 \(0751\)。
现在给定一个已经被加密过的四位数(称之为密文),请解密出原本的数字(称之为明文)。
【输入】
一行一个整数 \(n\),表示给定的密文,保证输入的密文有且仅有四个数字。
【输出】
一行一个正整数,表示对应的明文。
【输入样例】
0751
【输出样例】
8429
【核心思想】
-
问题分析:给定一个加密后的四位数,加密过程为:个位与千位对调、十位与百位对调,然后每位数字 \(x\) 替换为 \(9-x\)。要求解密出原始明文。这是一个逆向操作问题,关键在于发现加密操作的对合性(即加密和解密是同一操作)。
-
算法选择:
- 逆向提取:将密文的四位数字分别提取
- 对合解密:由于替换规则 \(x \to 9-x\) 是对合(应用两次还原),且对调操作也是对合,因此解密过程与加密过程完全相同
-
关键步骤:
- 初始化:读取四位密文 \(n\)
- 提取各位数字并解密:
a = 9 - n / 1000:千位数字解密(原个位)b = 9 - n / 100 % 10:百位数字解密(原十位)c = 9 - n / 10 % 10:十位数字解密(原百位)d = 9 - n % 10:个位数字解密(原千位)
- 输出明文:
d, c, b, a:按原顺序(千位、百位、十位、个位)输出
-
时间/空间复杂度:
- 时间复杂度:\(O(1)\),固定四位数字操作
- 空间复杂度:\(O(1)\),仅需四个变量
-
对合操作的核心思想:
- 对合性发现:加密中的两个操作(位置对调 和 数字替换 \(x \to 9-x\))都是对合(自逆),即 \(f(f(x)) = x\)。因此解密 = 加密
- 位置对调还原:加密时个位与千位对调,解密时同样的对调操作将位置还原
- 数字替换还原:\(9-(9-x) = x\),替换操作也是自逆
- 顺序处理:先对密文做数字替换,再对调位置,即得明文。代码中通过调整输出顺序
d, c, b, a实现位置还原 - 适用于"自逆变换 + 位置置换"类问题,识别对合性可大幅简化解密过程
【算法标签】
模拟
【代码详解】
#include <bits/stdc++.h>
using namespace std;
int n; // 输入的四位数
int a, b, c, d; // 四位数字的变量
int main()
{
cin >> n; // 输入一个四位数
// 计算千位数字的补数
a = 9 - n / 1000; // 提取千位数字,然后计算9减去它
// 计算百位数字的补数
b = 9 - n / 100 % 10; // 提取百位数字,然后计算9减去它
// 计算十位数字的补数
c = 9 - n / 10 % 10; // 提取十位数字,然后计算9减去它
// 计算个位数字的补数
d = 9 - n % 10; // 提取个位数字,然后计算9减去它
// 输出补数,注意顺序是倒过来的:个十百千
cout << d << c << b << a;
return 0; // 程序正常结束
}
【运行结果】
0751
8429
浙公网安备 33010602011771号