PAT 乙级练习 题解合集
题目
本题要求实现一种数字加密方法。首先固定一个加密用正整数 A,对任一正整数 B,将其每 1 位数字与 A 的对应位置上的数字进行以下运算:对奇数位,对应位的数字相加后对 13 取余——这里用 J 代表 10、Q 代表 11、K 代表 12;对偶数位,用 B 的数字减去 A 的数字,若结果为负数,则再加 10。这里令个位为第 1 位。
输入格式:
输入在一行中依次给出 A 和 B,均为不超过 100 位的正整数,其间以空格分隔。
输出格式:
在一行中输出加密后的结果。
输入样例:
1234567 368782971
输出样例:
3695Q8118
思路
我们要干啥?
题目隐藏了一些信息需要自己判断:两个字符串不等长的时候怎么办?
样例给的是b
比a
长 2 个字符的情况,b
的最高两位和原来相比没变,可以有两种解读方式:
b
比a
长的地方就不用处理了,所以没变;- 实际上
a
的高位自动补齐了0
,根据题目的要求,经过计算后b
的最高两位和原来一样,所以没变。
b
比a
长的时候怎么解读都行,反正答案是一样的,问题是 a
比b
长的时候 怎么办呢?我一开始觉得a
多出来的地方也不用处理了,于是错了几个测试点。事实上是需要把b
的高位用0
补齐的。
代码怎么写?
- 读入字符串
a
,b
后先全部反转,这样各个数位就对齐了(第 1 位是a[0]
和b[0]
); - 如果
b
比a
短,就在b
后面补齐字符0
直到他们长度相等; - 定义
len
为a
,b
中较短的那个字符串的长度,按照题意修改b
中前len
个元素即可。
代码
第一次 AC 的粗糙代码(C 语言)
#include <stdio.h>
#include <string.h>
#define MAX 110
char* reverse(char *str) {
int i, len = strlen(str);
for (i = 0; i < len/2; ++i) {
char temp = str[i];
str[i] = str[len - i - 1];
str[len - i - 1] = temp;
}
return str;
}
char* encrypt(char *a, char *b) {
reverse(a);
reverse(b);
if (strlen(b) < strlen(a)) {
int l = strlen(a) - strlen(b);
char *p = b + strlen(b);
while (l--)
*p++ = '0';
*p = '\0';
}
int i, len = strlen(a) < strlen(b) ? strlen(a) : strlen(b);
for (i = 0; i < len; ++i) {
if (i & 1)
b[i] = (b[i] - a[i] + 10) % 10 + '0';
else { // 这个地方写得太丑了,而且确实错了好几次才改对
b[i] = (b[i] + a[i] - '0' - '0') % 13 + '0';
if (b[i] > '9')
b[i] = (b[i] == '9' + 1 ? 'J' : b[i] == '9' + 2 ? 'Q' : 'K');
}
}
return reverse(b);
}
int main() {
char a[MAX], b[MAX];
scanf("%s %s", a, b);
printf("%s", encrypt(a, b));
return 0;
}
改进后(C 语言)
#include <stdio.h>
#include <string.h>
#define MAX 110
const char mod13[14] = "0123456789JQK";
char* reverse(char *str) {
int i, len = strlen(str);
for (i = 0; i < len/2; ++i) {
char temp = str[i];
str[i] = str[len - i - 1];
str[len - i - 1] = temp;
}
return str;
}
char* encrypt(char *a, char *b) {
reverse(a);
reverse(b);
if (strlen(b) < strlen(a)) {
int l = strlen(a) - strlen(b);
char *p = b + strlen(b);
while (l--)
*p++ = '0';
*p = '\0';
}
int i, len = strlen(a) < strlen(b) ? strlen(a) : strlen(b);
for (i = 0; i < len; ++i) {
if (i & 1)
b[i] = (b[i] - a[i] + 10) % 10 + '0';
else
b[i] = mod13[(b[i] + a[i] - '0' - '0') % 13];
}
return reverse(b);
}
int main() {
char a[MAX], b[MAX];
scanf("%s %s", a, b);
printf("%s", encrypt(a, b));
return 0;
}
C++
<algorithm>
下自带reverse
;- 在字符串后面添加
n
个相同的字符c
:string& append (size_t n, char c);
。
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
const string mod13 = "0123456789JQK";
string encrypt(string a, string b) {
reverse(a.begin(), a.end());
reverse(b.begin(), b.end());
if (a.size() > b.size())
b.append(a.size() - b.size(), '0');
int len = a.size() < b.size() ? a.size() : b.size();
for (int i = 0; i != len; ++i) {
if (i & 1)
b[i] = (b[i] - a[i] + 10) % 10 + '0';
else
b[i] = mod13[(b[i] + a[i] - '0' - '0') % 13];
}
reverse(b.begin(), b.end());
return b;
}
int main() {
string a, b;
cin >> a >> b;
cout << encrypt(a, b);
return 0;
}