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]); } }
|