1048 数字加密 (20 point(s))
// 错误魔改后正确版
#include <bits/stdc++.h>
using namespace std;
int main() {
// 加密整数A 加密序列B
string A, B, str = "0123456789JQK" ;
cin >> A >> B;
// 高位补零
// 获取A比B多出来的位数并转换为下标
for( int i = A.size() - B.size() - 1; i >= 0; i--){
B.insert(0, 1, '0');
}
int flag = 1;
// 右向左为高位 个位第一位
for(int i = A.size() - 1, j = B.size() - 1; i >= 0 && j >= 0; i--, j--){
// 每位数字 与A对应位置运算
// A奇数位置 相加后 13取余 J 10 Q 11 K 12
if(flag){
flag = 0;
// 直接替换B位置元素
int tmp = (int)(A[i] + B[j] - 2 * '0') % 13;
B[j] = str[tmp];
}
// 偶数 B 减去A 结果为负再加 10
else{
flag = 1;
int tmp = B[j] - A[i];
if(tmp < 0) tmp += 10;
B[j] = tmp + '0';
}
}
cout << B;
}
}
原来少考虑了一种情况。原本的想法是照着样例给出的一种条件,当 B 长于 A 的时候,高位 B 可以直接输出。所以最开始写的时候,仅仅只是考虑了 B > A 的时候。
并且最开始连 “与A对应位置运算” 这个条件也没有正确理解。以为左边才是对应的位置,从左边向右边一一对应。但结合另一个条件 “个位为第 1 位”,实际应该是从右边到左边为低位到高位,从右到左一一对应。
换句话来说就是左对齐和右对齐的区别,而这里则是右对齐。
所以这两个理解不正确,导致对 A < B 的时候没能够正确理解,同时因为没有正确位置上高位补零,导致卡测试点2。
学别人补零之后反而卡了测试点零、四五。结果一个个排除居然是奇偶位置判断的问题。
因为刚开始是照着题目要求判断奇偶位置的,结果发现由于下标会 - 1,导致用下标判断的话会导致奇偶结果互换。所以就从 i % 2 == 1 改成 i % 2 == 0 为奇数。
但这反而会导致测试点4和5的错误。最后学别人用flag记录,输出一个换一个处理方法,才能全部AC。
但还是不太理解,为什么会有这样的错误,难道奇偶不是隔一个出现?为什么会出现这样写判断会有问题?
不过看别人的代码,如果从屁股开始遍历的话,也可以用用 reverse() 函数将字符串倒置,而可以从 i = 0 开始遍历。
而这样写,就可以用 i & 2 来判断奇偶。真是神秘。
参考别人还学到两个东西,一个是关于字符数组比如
char str[13] = { '0','1','2','3','4','5','6','7','8','9','J','Q','K' };
可以写成
string str = "0123456789JQK";
这样就不需要写这么多 '' 了,使用上也是一致的。
还有就是字符串的拼接,原本以为是Java的,原来C++也可以实现这么方便的操作。比如别人高位补零的是这样写的。
while (A.size() < B.size()) { A = '0' + A; }
while (A.size() > B.size()) { B = '0' + B; }
写的时候注意的,关于数字字符的运算后转换成数字的问题。
如果是两个数字字符相加的时候,需要减去两个 '0',才能转换成真正的数字。
而相减的时候,因为数字字符本身带有 '0' ,所以相减的时候直接就减去了,直接就转换成真正的数字,不需要额外加减 '0'。
浙公网安备 33010602011771号