【PAT乙级】数字加密

正文索引 [隐藏]

题目描述:

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

输入描述:

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

输出描述:

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

输入样例:

1234567 368782971

输出样例:

3695Q8118

解题思路:

看完题目之后我的第一想法并不是像大多数人一样利用字符串的reverse来进行反转再求解,我首先想到的是利用堆栈后进先出的特点。就在我提交代码之后,满怀期待的等着全部AC的时候,有俩个测试用例显示了段错误。这就很难受啊,本菜鸡怎么修改都还是显示段错误,在我这个菜鸡各种求助之后,某大佬发现题目中并没有表明字符串b一定大于字符串a。然后感谢我的某位巨佬同学把这个bug修复了。她举了个例子,当输入”12 1″,即a=12 b=1时,我的代码输出结果是3,而根据题意可知正确答案应该是93。具体的修改方法是:如果字符串a的长度大于字符串b的长度,则在字符串b的前面补0,一开始就把b.length()-a.length()个0推入B栈来完成补0操作。其他地方完全不用改变。哈哈哈哈哈 提交之后AC。

AC代码:段错误代码:

#include <bits/stdc++.h>
using namespace std;

int main()
{
    string a,b;
    cin >> a >> b;
    stack<int> A;
    stack<int> B;
    for (int i = 0; i < a.length(); i++)
    {
        A.push(a[i]-'0');
    }
    for (int i = 0; i < b.length(); i++)
    {
        B.push(b[i]-'0');
    }
    int count = 1;   //位数
    stack<string> result;
    while(!A.empty())
    {
        if(count%2==0)   //对于偶数位
        {
            int temp = B.top()-A.top();  //用B的数字减去A的数字
            if(temp < 0)     //若结果为负数
            {
                temp += 10;   //再加10
            }
            result.push(to_string(temp));  //压入栈中
        }
        else     //对于奇数位
        {
            int temp = (B.top()+A.top())%13;   //对应位的数字相加后对13取余
            switch(temp)
            {
                case 10: result.push("J"); break;
                case 11: result.push("Q"); break;
                case 12: result.push("K"); break;
                default: result.push(to_string(temp)); break;
            }
        }
        count++;
        A.pop();   //删除A的栈顶元素
        B.pop();   //删除B的栈顶元素
    }
    while(!B.empty())   //若B中还有多余的元素
    {
        result.push(to_string(B.top()));
        B.pop();
    }
    while(!result.empty())
    {
        cout << result.top();
        result.pop();
    }
    return 0;
}

AC代码:

#include <bits/stdc++.h>
using namespace std;

int main()
{
    string a,b;
    cin >> a >> b;
    stack<int> A;
    stack<int> B;
    int lena = a.length();  //字符串a的长度
    int lenb = b.length();  //字符串b的长度
    if(lenb < lena)   //若字符串a比字符串b长
    {
        for (int i = 0; i < lena-lenb; i++)
        {
            B.push(0);  //将字符串b的开头进行补0,根据堆栈先进后出的特点,先把0入栈
        }
    }
    for (int i = 0; i < lena; i++)
    {
        A.push(a[i]-'0');
    }
    for (int i = 0; i < lenb; i++)
    {
        B.push(b[i]-'0');
    }
    int count = 1;   //位数
    stack<string> result;   //加密后的结果
    while(!A.empty())   //无论a长还是b长,加密的位数按照A的长度来
    {
        if(count%2==0)   //对于偶数位
        {
            int temp = B.top()-A.top();  //用B的数字减去A的数字
            if(temp < 0)     //若结果为负数
            {
                temp += 10;   //再加10
            }
            result.push(to_string(temp));  //压入栈中
        }
        else     //对于奇数位
        {
            int temp = (B.top()+A.top())%13;   //对应位的数字相加后对13取余
            switch(temp)
            {
                case 10: result.push("J"); break;
                case 11: result.push("Q"); break;
                case 12: result.push("K"); break;
                default: result.push(to_string(temp)); break;  //把int型的数字变成string型
            }
        }
        count++;
        A.pop();   //删除A的栈顶元素
        B.pop();   //删除B的栈顶元素
    }
    while(!B.empty())   //若B中还有多余的元素,则把它们全部推入栈中
    {
        result.push(to_string(B.top()));  
        B.pop();
    }
    while(!result.empty())   //清仓大甩卖
    {
        cout << result.top();  //输出加密后的结果
        result.pop();
    }
    return 0;
}