PAT乙级.1048. 数字加密(20)

1048. 数字加密(20)


题目

本题要求实现一种数字加密方法。首先固定一个加密用正整数A,对任一正整数B,将其每1位数字与A的对应位置上的数字进行以下运算:对奇数位,对应位的数字相加后对13取余——这里用J代表10、Q代表11、K代表12;对偶数位,用B的数字减去A的数字,若结果为负数,则再加10。这里令个位为第1位。

输入格式

输入在一行中依次给出A和B,均为不超过100位的正整数,其间以空格分隔。

输出格式

在一行中输出加密后的结果。

输入样例

1234567 368782971

输出样例

3695Q8118

PAT链接


思路:

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起始位置在数组中间,位置可以向前移
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值