2020 CCPC-Wannafly Winter Camp Day 1 B

Problem B. 密码学

Statement

将小写字母从 $0$ 到 $25$ 编号,将大写字母从 $26$ 到 $51$ 编号。用字符 $a$ 加密字符 $b$ 得到的字符,是 $a$ 和 $b$ 的编号相加后对 $52$ 取余后的结果对应的字符。用字符串 $key$ 加密字符串 $s$ 得到的字符串长度与 $s$ 相同,其中,第 $i$ 个字符是用 $key_i$ 加密 $s_i$ 得到的字符,如果 $key$ 的长度不够,则将 $key$ 重复多次。

有 $n$ 个字符串 $s_1,s_2,\dots,s_n$ 和 $m$ 次加密操作 $(x_1,y_1),(x_2,y_2),\dots,(x_n,y_n)$。第 $i$ 次加密操作用 $s_{x_i}$ 加密 $s_{y_i}$,并将 $s_{y_i}$ 替换为加密结果。现在给出 $n$ 个字符串的最终结果和 $m$ 次加密操作,求 $n$ 个字符串的初始值。

$1 \leq n,m \leq 1000$, $1 \leq x_i,y_i \leq n$

$1 \leq |s_i| \leq 100$

Solution

模拟题,没啥好说的……加密是加解密就是减……

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;

const int N = 1e5 + 5;
int x[N], y[N];
char s[N][105];

int chartoint (char c) {
if (('a' <= c) && (c <= 'z')) return c - 'a';
if (('A' <= c) && (c <= 'Z')) return c - 'A' + 26;
}

char inttochar (int a) {
if ((0 <= a) && (a <= 25)) return a + 'a';
if ((26 <= a) && (a <= 51)) return a - 26 + 'A';
}

int main () {
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1;i <= m;i++) {
scanf("%d%d", &x[i], &y[i]);
}
for (int i = 1;i <= n;i++) {
scanf("%s", &s[i]);
}

for (int i = m;i >= 1;i--) {
int lx = strlen(s[x[i]]);
int ly = strlen(s[y[i]]);
for (int j = 0;j < ly;j++) {
int tmp = 0;
tmp += chartoint(s[y[i]][j]);
tmp -= chartoint(s[x[i]][j % lx]);
tmp += 52;
tmp %= 52;
s[y[i]][j] = inttochar(tmp);
}
}

for (int i = 1;i <= n;i++) {
printf("%s\n", s[i]);
}
}