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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章