PAT 1024 Palindromic Number (大整数相加)

来源:互联网 发布:漫画控连接不了网络 编辑:程序博客网 时间:2024/06/06 02:29

题目

https://www.patest.cn/contests/pat-a-practise/1024

已知非回文串可以通过不断和自身逆序相加来得到回文串,称为一次操作,如67+76=143+341=484的操作次数为2。给定一个正数N和操作的最大次数,判断该数串在最大操作次数内能否得到回文串。

解题思路

由于N最大可以为10^10,操作次数最多可以为100次,所以数字长度会很长,在long long int内会溢出,所以必须要用大整数相加。

用二维数组num存放每一次操作得到的数字(num[0]为输入的原始数字)一维数组row_cnt记录num每一行的数字有效长度。第step次运算前先判断是否已经得到回文串,若已经得到则跳出循环,否则取num[step-1]这一行的数字进行逆序相加和判断进位,存放到num[step]这一行,更新row_cnt[step]。

第一次交的时候测试点6和8都没有通过,仔细检查了代码是没有问题的,后来看了大神博客才知道是二维数组的列宽太小了,20和50都不够,100才能全部通过。(有可能每次都要溢出进位,所以今后要想清楚了再声明啊!)

自己的方法太复杂了,https://www.liuchuo.net/archives/2329这篇博客里用STL的string和reverse来快速解题。真是高下立见。
STL的方法如下:
判断回文串只需reverse当前字符串s得到t,用s==t来判断是否回文。
计算时也只需要将t逐位加到s上,判断进位,(正着加和反着加是没有区别的,为自己智商捉急),最后将s逆序即得到这一次操作后的结果。

AC代码

复杂的二维数组法

#include <iostream>#include <cstring>using namespace std;int num[110][100]; //存放每一步的运算结果int row_cnt[110] = {0}; //num矩阵每行的有效数字长度void print(int row) //输出第row行数字{    for (int j = row_cnt[row] - 1; j >= 0; --j)        cout << num[row][j];    cout << endl;}bool isPalindromic(int row) //判断第row行是不是回文数字{    bool flag = true;    int maxj = row_cnt[row];    for (int j = 0; j <= maxj/2; ++j) //判断回文串    {        if (num[row][j] != num[row][maxj-1-j])        {            flag = false;            break;        }    }    return flag;}int main(){    memset(num, 0, sizeof(num));    int limit;    char str[20];    cin >> str >> limit;    int j = 0;    for (int i = strlen(str)-1; i >= 0; --i)        num[0][j++] = str[i] - '0';    row_cnt[0] = j;    int step = 0;    while(step < limit)    {        bool check = isPalindromic(step);        if (check)        {            print(step);            cout << step << endl;            return 0;        }        step += 1;        int last = row_cnt[step-1]; //last为上一行的数字长度        for (int j = 0; j < last; ++j) //逆序相加        {            num[step][j] += num[step-1][j] + num[step-1][last-1-j];            num[step][j+1] = num[step][j] / 10;            num[step][j] %= 10;        }        row_cnt[step] = (num[step][last] == 0)?last:last+1;    }    print(step);    cout << limit << endl;    return 0;}

简练的STL大法:

#include <iostream>#include <algorithm>#include <string>using namespace std;string s;void add(){    string t = s;    reverse(t.begin(), t.end());    int len = s.length(), carry = 0;    for (int i = 0; i<len; ++i) //将t各位累加到s上    {        s[i] = s[i] + t[i] + carry - '0'; //注意s是字符串        if (s[i] > '9') //要用字符'9'判断进位        {            s[i] = s[i] - 10;            carry = 1;        }        else carry = 0;    }    if (carry == 1) s += '1'; //溢出进位    reverse(s.begin(), s.end());}int main(){    int limit;    cin >> s >> limit;    int step = 0;    while (step < limit)    {        string t = s;        reverse(t.begin(), t.end());        if (s == t) //判断回文        {            cout << s << endl << step;            return 0;        }        step += 1;        add();    }    cout << s << endl << step;    return 0;}