​题目传送门​


题目描述

考虑一种加密方式,它需要一个任意长度的原文 {m}m 和秘钥 {key}key,其中要求原文和秘钥只包含大写和小写的英文字符。
首先定义字符之间的加密,用字符 2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_字符串 去加密字符 2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_#include_02

  • 首先把2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_字符串_032020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_#include_04转成数字2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_字符串_052020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_算法_06。转换的规则是,小写字母2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_字符串_032020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_返回结果_08依次对应2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_#include_092020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_算法_10,大写字母依次对应2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_算法_112020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_字符串_12
  • 计算2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_字符串_052020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_算法_06的和2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_返回结果_08,对2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_算法_16取模,即计算2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_返回结果_17
  • 返回数字2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_返回结果_08

现在来讲如何用秘钥 2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_算法_19 来加密原文 2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_#include_20

  • 如果秘钥的2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_算法_21的长度小于2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_算法_22,那么不停重复2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_算法_21直到长度不小于2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_算法_22为止。举例来说,如果原文是2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_字符串_25,秘钥是2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_算法_26,那么秘钥需要被重复称2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_#include_27
  • 假设原文的长度是2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_#include_28,那么对于每一个2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_#include_29的数字2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_返回结果_30,都用2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_算法_21的第2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_返回结果_30个字符去加密2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_算法_22的第2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_返回结果_30
  • 返回结果。

那么用 2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_字符串_35 去加密 2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_#include_36 的结果就是:2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_#include_37
现在火山哥有 2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_算法_38 个字符串,2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_返回结果_392020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_#include_40,他对这些字符串做了2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_#include_20 次加密操作:第 2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_算法_42 次加密操作用第 2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_#include_43 去加密 2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_字符串_44,并把 2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_返回结果_45 替换成加密结果。
现在依次给出 2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_#include_20 次加密操作,以及加密操作结束后每一个字符串的模样,你可以还原出这 2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_算法_38


输入描述:

第一行输入两个整数 2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_算法_48 2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_返回结果_49
接下来 2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_#include_20 行每行输入两个整数 2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_#include_51,表示依次加密操作,保证 2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_#include_52 不等于 2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_算法_53
接下来 2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_算法_38 行每行输入一个字符串,表示加密最后的结果。字符串的长度在 2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_算法_552020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_字符串_56


输出描述:

输出 2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_算法_38


输入

2 1
1 2
PKUSAA
QOcbINV


输出

PKUSAA
beijing


题解

  • easy
  • 题面中给出了已知原文和秘钥,加密得到密文的方法。其实已知密文和秘钥,就可以轻松的解密出原文:只要用密文对应的数字减去秘钥对应的数字就可以了。
    因此,我们可以从后往前“撤销”所有加密操作带来的影响。假设最后一次加密操作是用2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_返回结果_58去加密2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_字符串_59,那么在结果中,2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_返回结果_58是没有发生变化的,即秘钥已知;2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_字符串_59,存储的是结果,即密文已知。从而用上面的方法可以直接从两者之中推出2020 CCPC Wannafly Winter Camp Day1 Div.1&2——密码学【构造 & 模拟】_字符串_59,原来的值。
  • 所以从后往前考虑每一次加密操作,依次进行撤销,最后得到的就是最开始的 nn 个字符串。

AC-Code

#include <bits/stdc++.h>
using namespace std;

int xi[1005], yi[1005];
string str[1005];
int f1(char c) { return c > 'Z' ? c - 'a' : c - 'A' + 26; }
char f2(int x) { return x >= 26 ? 'A' + x - 26 : 'a' + x; }
void sub(char& s1, char& s2) {
s2 = f2((f1(s2) - f1(s1) + 52) % 52);
}
void solve(int a, int b) {
for (int i = 0, j = 0; str[b][j]; ++i, ++j) {
if (!str[a][i])
i = 0;
sub(str[a][i], str[b][j]);
}
}
int main() {

int n, m;
while (cin >> n >> m) {
for (int i = 0; i < m; ++i)
cin >> xi[i] >> yi[i];
for (int i = 1; i <= n; ++i)
cin >> str[i];
for (int i = m - 1; i >= 0; --i)
solve(xi[i], yi[i]);
for (int i = 1; i <= n; ++i)
cout << str[i] << endl;
}
return 0;
}