题目背景
方方方很喜欢回文数,于是就有了一道关于回文数的题目。
题目描述
求从小到大第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]); }