1048. 数字加密(20)
题目
本题要求实现一种数字加密方法。首先固定一个加密用正整数A,对任一正整数B,将其每1位数字与A的对应位置上的数字进行以下运算:对奇数位,对应位的数字相加后对13取余——这里用J代表10、Q代表11、K代表12;对偶数位,用B的数字减去A的数字,若结果为负数,则再加10。这里令个位为第1位。
输入格式
输入在一行中依次给出A和B,均为不超过100位的正整数,其间以空格分隔。
输出格式
在一行中输出加密后的结果。
输入样例
1234567 368782971
输出样例
3695Q8118
思路:
1.这种从后向前比对的题目,反转字符串的话会比较简单。可以先反转字符串,再从前向后依次加密。注意:如果B的位数比A小,要将少的位按数字0补充后再进行加密。
2.不反转字符串的话本来也很方便,从后向前依次比对,分奇偶进行加密,要注意数字与字符之间的转换。
但是!!!由于:如果B的位数比A小,要将少的位按数字0补充后再进行加密。
解决方法是:开一个更大的缓冲区,记录加密后字符串的实际起始位置:
思路参考其他博客
char strA[110], buf_b[220]; //strA起始位置在数组开头
char *strB = buf_b+110; //strB起始位置在数组中间,位置可以向前移
代码:
version1.0(不反转字符串)
/**
* @tag PAT_B_1048
* @authors R11happy (xushuai100@126.com)
* @date 2016-8-27 18:14-
* @version 1.0
* @Language C++
* @Ranking 455/1411
* @function 不反转字符串的做法
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
char mod13[] = "0123456789JQK";
char strA[110], buf_b[220]; //strA起始位置在数组开头
char *strB = buf_b+110; //strB起始位置在数组中间,位置可以向前移
int main(int argc, char const *argv[])
{
scanf("%s%s", strA, strB);
int lenA = strlen(strA);
int lenB = strlen(strB);
int currA = lenA - 1;
int currB = lenB - 1;
for (; currA >= 0; currA--, currB--)
{
//题目真实意思是当lenB < lenA的时候,把strB的少的位数按0来进行数字加密
if(currB<0) strB[currB] = '0';
//奇数位,相应位相加后对13取余
if ((lenB - currB) % 2 == 1)
{
int sum = (strA[currA] - '0') + (strB[currB] - '0');
strB[currB] = mod13[sum % 13];
}
//偶数位相减
else
{
int numA = strA[currA] - '0';
int numB = strB[currB] - '0';
int sub = numB - numA;
if (sub < 0) sub += 10;
strB[currB] = sub + '0';
}
}
if(lenB < lenA) puts(strB+currB+1); //起始位置前移的情况
else printf("%s\n", strB); //正常起始位置
return 0;
}
version2.0(反转字符串)
/**
* @tag PAT_B_1048
* @authors R11happy (xushuai100@126.com)
* @date 2016-8-27 18:14-
* @version 2.0
* @Language C++
* @Ranking 455/1411
* @function 反转字符串的做法
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
char mod13[] = "0123456789JQK";
const int Max = 110;
char strA[Max], strB[Max], ans[Max];
void reverse(char s[])
{
int len = strlen(s);
for(int i = 0; i < len/2; i++) //注意:不能写成i <= len/2
{
int tmp = s[i];
s[i] = s[len -1 - i];
s[len -1 - i] = tmp;
}
}
int main(int argc, char const *argv[])
{
scanf("%s%s", strA, strB);
int lenA = strlen(strA);
int lenB = strlen(strB);
reverse(strA); //将strA和strB反转
reverse(strB);
int len = lenA > lenB? lenA: lenB; //取长的
for(int i = 0; i<len; i++)
{
int numA = i<lenA? strA[i] - '0': 0; //strA[i]位置字符对应的数字
int numB = i<lenB? strB[i] - '0': 0; //strB[i]位置字符对应的数字
if(i%2 == 0 ) //对应加密算法的奇数位
{
int sum = numA + numB;
ans[i] = mod13[sum%13];
}
else //对应加密算法的偶数位
{
int sub = numB - numA;
if(sub < 0 ) sub += 10;
ans[i] = sub + '0';
}
}
reverse(ans); //反转输出
puts(ans);
return 0;
}
收获:
利用开缓冲区的方式,解决字符串要向前append的情况
char strA[110], buf_b[220]; //strA起始位置在数组开头
char *strB = buf_b+110; //strB起始位置在数组中间,位置可以向前移