洛谷U3348 A2-回文数

U3348 A2-回文数

题目背景

方方方很喜欢回文数,于是就有了一道关于回文数的题目。

题目描述

求从小到大第n(1<=n<=10^18)个回文数。

注释:出题人认为回文数不包括0。

输入输出格式

输入格式:

 

一行一个正整数n。

 

输出格式:

 

第n个回文数。

 

输入输出样例

输入样例#1:
2333
输出样例#1:
1334331
输入样例#2:
12345678987654321
输出样例#2:
23456789876543222234567898765432

说明

对于50%的数据,n<=3000。

对于100%的数据,1<=n<=10^18。..

/*
    找规律题
    我们发现一个输出对应着输入数据首位-1,末位-1,然后进行对称变换 
    细节有三个:
    1.如果前两项为10,需要把1减去,0变成9
    2.如果末项为9,加1之后向前进位 
    3.对称变换需要考虑对称轴是最后一位数还是最后一位数后面的位置,这就需要提前预处理输出结果一共有几位数 
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
long long sum[60],a[60];
long long n;
int bin[1000],len,b[1000];
long long pow(int mi){
    long long res=1;
    for(int i=1;i<=mi;i++)res*=10;
    return res;
}
int main(){
    freopen("hws.in","r",stdin);
    freopen("hws.out","w",stdout);
    for(int i=1;i<=37;i++){
        int mi=((i+1)/2-1);
        a[i]=1LL*9*pow(mi);
        sum[i]=sum[i-1]+a[i];
    }
    cin>>n;
    int pos=lower_bound(sum+1,sum+38,n)-sum;//pos就是数的位数 
    if(n==sum[pos-1])pos--;
    //cout<<pos<<endl;
    while(n){
        b[++len]=n%10;
        n/=10;
    }
    for(int i=1,j=len;i<=len;i++,j--)bin[i]=b[j];
    bin[1]--;bin[len]++;
    if(bin[1]==0&&bin[2]==0)bin[2]=9;
    int now=len;
    while(bin[now]>=10){
        bin[now-1]+=bin[now]/10;
        bin[now]%=10;
        now--;
    }
    int l=len,r=len+1;
    if(pos%2==1)l--;
    while(l>=1){
        bin[r]=bin[l];
        l--;r++;
    }
    l=1,r--;
    while(bin[l]==0)l++;
    while(bin[r]==0)r--;
    for(int i=l;i<=r;i++)printf("%d",bin[i]);
}

 

posted @ 2017-09-15 15:14  Echo宝贝儿  阅读(152)  评论(0编辑  收藏  举报