如果一个正整数自身是回文数,而且它也是一个回文数的平方,那么我们称这个数为超级回文数。
现在,给定两个正整数 L
和 R
(以字符串形式表示),返回包含在范围 [L, R]
中的超级回文数的数目。
提示:
1 <= len(L) <= 18
1 <= len(R) <= 18
L
和 R
是表示 [1, 10^18)
范围的整数的字符串。
int(L) <= int(R)
这个问题其实并不复杂,难就难在数据的大小,题目给出的L
和R
的数据范围中,最高可达到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=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=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