hnust

来源:互联网 发布:电脑禁止安装软件 编辑:程序博客网 时间:2024/04/28 23:10

题目描述

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

输入

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

输出

输出标号为n的回文数。

样例输入

1 2 3 4

样例输出

1234

来源

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 <iostream>#include <cstdio>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<<index<<endl;    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;}
原创粉丝点击