超级回文数--处理大数的基本思路

0x01.问题

如果一个正整数自身是回文数,而且它也是一个回文数的平方,那么我们称这个数为超级回文数。
现在,给定两个正整数 LR (以字符串形式表示),返回包含在范围 [L, R] 中的超级回文数的数目。
提示:
1 <= len(L) <= 18

1 <= len(R) <= 18
LR 是表示 [1, 10^18) 范围的整数的字符串。
int(L) <= int(R)

0x02.大数处理思路

这个问题其实并不复杂,难就难在数据的大小,题目给出的LR的数据范围中,最高可达到10^18,首先就算不管数据范围,一个一个的试,时间那关肯定过不去,因为计算机要运行的次数实在是太多了,再者,在一个大数上操作,可能一不小心就超出数据范围,导致不可控错误,所以,我们一定要想办法把这个大数变小。

一个数是回文数,且它是一个回文数的平方,就是超级回文数,相反的,如果我们确定了一个数是回文数,那么,如果它的平方也是回文数,那么,超级回文数的个数就加1,我们需要循环的次数就减少到了10^9,但是这样,还是太多了,我们还得想办法降低一下。

我们仔细思考一下,我们真的有必要去判断每一个数是不是回文数吗?

其实并不是,我们要找的是超级回文数,所以我们可以先生存一个回文数,如何生成?

一个一个数字取反再加到这个数字上,新的数字就是一个回文数,也就是说,我们只要生成一个一定范围内的回文数,再对它进行平方,判断是不是回文数就行了,刚才提到的范围是10^9,那么我们可以从多大的范围内生成这个回文数呢?

回文数分奇偶,包含奇偶两种情况下,最大用来生成回文数的数字是10^5,这个次数就比较可观了,并且我们只需要分奇偶两次遍历就行了。

这样,一个大数问题,就成功的被我们降低到了可处理范围。

0x03.解决代码

class Solution {
public:
    bool isPalindrome(long long x){
        return x==reverse(x);
    }
    long long reverse(long long x){
        long long ans=0;
        while(x>0){
            ans=10*ans+x%10;
            x/=10;
        }
        return ans;
    }
    int superpalindromesInRange(string L, string R) {
        long long LL=stoll(L);
        long long RR=stoll(R);
        int ans=0;
        for(int k=0;k<100000;k++){
            string s=to_string(k);
            for(int i=s.size()-2;i>=0;i--){
                s+=s[i];
            }
            long long a=stoll(s);
            a*=a;
            if(a>RR) break;
            if(a>=LL&&isPalindrome(a)) ans++;
        }
        for(int k=0;k<100000;k++){
            string ss=to_string(k);
            for(int i=ss.size()-1;i>=0;i--){
                ss+=ss[i];
            }
            long long b=stoll(ss);
            b*=b;
            if(b>RR) break;
            if(b>=LL&&isPalindrome(b)) ans++;
        }
        return ans;
    }
};

0x04.大数处理的根本–降低次数

ATFWUS  --Writing  By 2020–03–20

你可能感兴趣的:(算法,算法,回文数,超级回文数,大数处理,C++)