POJ 2402 Palindrome Numbers(LA 2889) 回文数
POJ:http://poj.org/problem?id=2402
题目大意:
回文数从小到大排列为:1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, ……输入n,(1<=n<=2*10^9),求第n小的回文数。
思路:
我们先统计一下i个数字组成的回文数的个数,cnt[i]=cnt[i-1]+9*mypow(10,p);
然后第n个回文数只要看看他是几位的就可以了。
如n=520,求出他需要5位,而1~4位所有的回文数个数(总的)为198,故k=520-198=322
找100为三位的基准,(为什么是3位? 长度为5的一般,向上取整。。为什么是100,三位最小哇)
100+k-1=100+321=421
所以一半求出来了,另一半呢(T T不是指对象)
根据对称性,可得42124
版本一:
#include<cstdio> #include<cstring> #include<cmath> typedef long long LL; const int MAXN=20; LL cnt[MAXN]={0}; char ans[MAXN]; LL mypow(LL x,LL p) { long long res=1; while(p--) res*=x; return res; } int main() { for(int i=1;i<MAXN;i++) { LL p=(i+1)/2-1; cnt[i]=cnt[i-1]+9*mypow(10,p); } int n; while(~scanf("%d",&n),n) { int k,num; for(int i=1;i<MAXN;i++) { if(n <= cnt[i]) //万恶的等于号!!!! { k=n-cnt[i-1];//还需要的个数 num=i; //位数 break; } } int len=num; num=(num+1)/2; LL x=mypow(10,num-1)+k-1; printf("%lld",x); if(len %2!=0) x/=10; while(x) { printf("%lld",x%10); x/=10; } printf("\n"); } return 0; }
版本二:(请选择G++提交,因为pow函数要double而我是long long ,c++会说CP)
#include<cstdio> #include<cmath> #include<cstring> typedef long long LL; const int MAXN=22; LL cnt[MAXN]={0}; char ans[MAXN]; int main() { for(int i=1;i<MAXN;i++) { LL p=(i+1)/2-1; cnt[i]=cnt[i-1]+9*pow(10,p); } int n; while(~scanf("%d",&n),n) { int k,num; for(int i=1;i<MAXN;i++) { if(n <= cnt[i]) { k=n-cnt[i-1]; num=i; break; } } LL x=pow(10,(num+1)/2-1); x+=k-1; sprintf(ans,"%lld",x); int len=strlen(ans); for(int i=0;i<len;i++) printf("%c",ans[i]); if(num &&num % 2==0) printf("%c",ans[len-1]); for(int i=len-2;i>=0;i--) printf("%c",ans[i]); printf("\n"); } return 0; }
新 blog : www.hrwhisper.me