题解:学而思编程 数字加密

【题目来源】

学而思编程:数字加密

【题目描述】

对一个十进制的四位数来说,我们可以用以下过程将它加密成另一个四位数:

首先,将个位和千位对调;

然后,将十位和百位对调;

最后每位 \(0\) 换成 \(9\),每位 \(1\) 换成 \(8\),每位 \(2\) 换成 \(7\)\(\ldots\),每位 \(9\) 换成 \(0\)

例如,对 \(8429\) 加密,则

个位和千位对调后得 \(9428\)

十位和百位对调后得 \(9248\)

将每个数字替换后得 \(0751\)

现在给定一个已经被加密过的四位数(称之为密文),请解密出原本的数字(称之为明文)。

【输入】

一行一个整数 \(n\),表示给定的密文,保证输入的密文有且仅有四个数字。

【输出】

一行一个正整数,表示对应的明文。

【输入样例】

0751

【输出样例】

8429

【核心思想】

  1. 问题分析:给定一个加密后的四位数,加密过程为:个位与千位对调、十位与百位对调,然后每位数字 \(x\) 替换为 \(9-x\)。要求解密出原始明文。这是一个逆向操作问题,关键在于发现加密操作的对合性(即加密和解密是同一操作)。

  2. 算法选择

    • 逆向提取:将密文的四位数字分别提取
    • 对合解密:由于替换规则 \(x \to 9-x\) 是对合(应用两次还原),且对调操作也是对合,因此解密过程与加密过程完全相同
  3. 关键步骤

    • 初始化:读取四位密文 \(n\)
    • 提取各位数字并解密
      • a = 9 - n / 1000:千位数字解密(原个位)
      • b = 9 - n / 100 % 10:百位数字解密(原十位)
      • c = 9 - n / 10 % 10:十位数字解密(原百位)
      • d = 9 - n % 10:个位数字解密(原千位)
    • 输出明文
      • d, c, b, a:按原顺序(千位、百位、十位、个位)输出
  4. 时间/空间复杂度

    • 时间复杂度:\(O(1)\),固定四位数字操作
    • 空间复杂度:\(O(1)\),仅需四个变量
  5. 对合操作的核心思想

    • 对合性发现:加密中的两个操作(位置对调 和 数字替换 \(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
posted @ 2026-07-05 14:49  团爸讲算法  阅读(12)  评论(0)    收藏  举报