用算法查找回文

时间:2018-11-20 16:46:47

标签: c++

我得到的数字N <= 200,我只需要使用此算法找到palindrom,然后输出palindrom和迭代次数:

1)逆向

2)撤消号码+上一个

示例:

  
    

1)N = 99

  
     

出99 0

     
    

2)N = 69

  
     

69 + 96 = 165 165 + 561 = 726 726 + 627 = 1353 1353 + 3531 = 4884

     

出场:4884 4

我的代码:

#include <iostream>

using namespace std;

int rev(int a)
{
    int b = 0;
    while (a)
    {
        b = 10 * b + a % 10;
        a /= 10;
    }

    return b;
}

int main()
{
    ios::sync_with_stdio(0);
    int n, c = 0;
    cin >> n;
    while (n != rev(n))
    {
        n = n + rev(n);
        c++;
    }
    cout << n << endl << c;
    return 0;
}

它仅适用于100个测试中的70个:(

您能帮助我,使其适用于所有测试吗?

1 个答案:

答案 0 :(得分:1)

这仅仅是整数溢出的问题。第一个实现是用unsigned long long实现的。它似乎可以正常工作,但未检测到一些溢出。

使用__int128执行了新的实现。此外,使用了签名版本,以便能够轻松检测溢出。

现在,对于介于1和200之间的n,找到所有回文,但n = 196除外,这是检测到溢出的原因。

这是程序:

#include <iostream>

//using namespace std;

void print128 (__int128 a) {
    __int128 v64 = (__int128) 1 << 64;
    __int128 high128 = a / v64;
    __int128 low128 = a % v64;
    unsigned long long high =  high128;
    unsigned long long low =  low128;
    if (high > 0) std::cout << high;
    std::cout << low;
}

__int128 rev(__int128 a) {
    __int128  b = 0;
    while (a) {
    b = 10 * b + a % 10;
    a /= 10;
    }
    return b;
}

int main() {
    //std::ios::sync_with_stdio(0);

    int nerr = 0;
    int cmax = 100000;
    for (int n0 = 10; n0 <= 200; n0++) {
        bool overf = false;
        int c = 0;
        __int128  nrev;
        __int128 n = n0;
        while ((n != (nrev = rev(n))) && (c < cmax)) {
            if (nrev < 0) overf = true;
            n = n + nrev;
            if (n < 0) overf = true;
            c++;
        }
        std::cout << "n = " << n0 << " ";;
        if ((c == cmax) && !overf) {
            std::cout << " ERR0R\n";
            nerr++;
        } else if (overf) {
            std::cout << " OVERFLOW\n";
            nerr++;
        } else {            
            std::cout << " palym = ";
            print128 (n);
            std::cout << "  c = " << c << "\n";
        }
    }
    std::cout << "Nbre of errors = " << nerr << "\n";
    return 0;
}

问题是“对196案该怎么办?”我们不知道是否存在解决方案,即是否存在收敛。而且,如果收敛,我们将不知道回文的大小。尝试将int与更多的位一起使用可能是一场漫长的竞赛。更好的方法是实现一个适合于该问题的专用int类型,即一个int向量,每个int在0到9之间。对于该算法,我们只有两个操作要执行,计算回文和加法。计算回文将是微不足道的,将向量的元素求逆(忽略第一个零),并且加法将很容易实现。而且,这样的添加将容易检测溢出。最后但并非最不重要的是,向量的大小可能适用于每个n值,直到给定限制为止。

编辑:在评论中,马克·兰瑟姆(Mark Ransom)提供了有关Lychrel数字的Wikipedia页面的链接,该数字即算法将不会收敛的数字。最低和最著名的“候选人Lychrel”编号196是。据推测,没有证明196是这样的数字。实验一直进行到数十亿个数字为止,但没有找到这个数字的收敛性。