hnust - 求第几个回文数

题目描述

据说上一次的素数回文把aigo难了一把,悲剧了几把。今天aigo又接到陈老大的一个任务,但是aigo最近搞学习有点累了,想请聪明的你帮忙解决。
回文数是可以从1开始的,现给每一个回文数一个标号,从1开始,所以9的标号是9了,请求出标号为n的回文数。

输入

多组测试数据,每组一行,只有一个整数n,1<=n<=2*10^9.

输出

输出标号为n的回文数。

样例输入

1 
2 
3 
4

样例输出

1
2
3
4

来源

hnust-oj-1146-伤不起的回文数

题解

思路

  • 看到n可以取到2*10^9.说明普通方法一个个暴力计算肯定会超时的,那打表呢?打表我们要先写个打表的代码,这里不提供。打完表观察数据,我们会发现数据其实是有规律的。完全不需要暴力的把所有数据打出来了!
  • 通过数据我们发现,第n个回文数的规律如下:
    • 1位的回文数有9个
      2位的回文数有9个
      3位的回文数有90个
      4位的回文数有90个
      5位的回文数有900个
      6位的回文数有900个
      ……
    • 原因是什么呢,如四位数的回文数个数,我们只看字符串的一半,从1001到9999,只看一半就是共有90个回文数。
    • 通过这样的规律,我们知道,只要数位增加2位,相应的该数位回文数就会是上位的10倍。
    • 编码过程就是,先算出这个回文数有几位,然后算该位数下最小的回文数与该回文数的距离(回文数以一半为基准算)。时间复杂度几乎为O(1),而之前的循环判断回文数并记数的方法明显快。

代码

#include 
#include 
using namespace std;
long long findhw(long long index)
{
    long long res,cnt=0,w=0,num=9,half=1;
    while(1)
    {
        if(w>0&&w%2==0){
            num*=10;
        }
        w++;
        if(cnt+num>=index)
            break;
        cnt+=num;
    }
    index=index-cnt-1;
    //cout<
    int i;
    for(i=0;i<(w-1)/2;i++)
    {
        half*=10;
    }
    half+=index;
    res=half;
    if(w%2==1)
    {
        half/=10;
    }
    while(half){
        res=res*10+half%10;
        half/=10;
    }
    return res;

}
int main()
{
    long long n;
    while(scanf("%lld",&n)!=EOF)
    {
        printf("%lld\n",findhw(n));
    }
    return 0;
}

你可能感兴趣的:(C/C++,回文数)