PAT 1024 Palindromic Number (大整数相加)

题目

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值