这题目关键是打表,haha[k]数组表示的是S1S2..Sk该串结尾所在的位置。然后用n去找n所在的k值,此时haha[k-1]<n<=haha[k]。然后再算出从haha[k]位置到n一共有多少位,再查出来就行了。
本来我要用打表+二分的想法,不过后来二分写的不太好一看可以直接遍历就遍历,limit=3万多,直接遍历也行!有时间把这个二分好好的重写一下。
一点没看题解,做出来挺开心的!
1-9 的长度 = 9
1-99 的长度 = 189
1-999 的长度 = 2889
1-9999的长度 = 38889
31268是事先计算好的,haha[31268]时候正好大于临界值。
1 #include <stdio.h> 2 #define limit 31268 3 long long haha[100000]; 4 void init(){ 5 int cnt=1,i; 6 int t; 7 haha[0]=0; 8 for(i=1;i<=65537;++i){ 9 haha[i]=haha[i-1]; 10 if(cnt>=10000){ 11 haha[i]+=(cnt-10000+1)*5+38889; 12 } 13 else if(cnt>=1000){ 14 haha[i]+=(cnt-1000+1)*4+2889; 15 }else if(cnt>=100){ 16 haha[i]+=(cnt-100+1)*3+189; 17 }else if(cnt>=10){ 18 haha[i]+=(cnt-10+1)*2+9; 19 }else if(cnt>0){ 20 haha[i]+=1*cnt; 21 } 22 cnt++; 23 if(haha[i]>2147483647){ 24 break; 25 } 26 } 27 return ; 28 } 29 int main(){ 30 int t,ii,i,l,r,mid; 31 int n; 32 int pos; 33 int cnt; 34 int tmp; 35 int res; 36 init(); 37 while(~scanf("%d",&t)){ 38 while(t--){ 39 scanf("%d",&n); 40 /* 41 l=0; 42 r=limit; 43 mid=(r+l)/2; 44 while(haha[r]>=n&&n>=haha[l]){ 45 printf("l=%d,r=%d,haha[l]=%lld,haha[r]=%lld\n",l,r,haha[l],haha[r]); 46 if(n<haha[mid]){ 47 r=mid; 48 }else if(n>haha[mid]) 49 l=mid; 50 else break; 51 mid=(r+l)/2; 52 } 53 pos=mid; 54 */ 55 for(i=0;i<=limit;++i){ 56 if(haha[i]>=n) 57 break; 58 } 59 pos=i; 60 cnt=0; 61 res=-1; 62 // printf("n=%d,pos=%d,haha[pos]=%lld\n",n,pos,haha[pos]); 63 if(n-(int)haha[pos]<0){ 64 n=(int)haha[pos]-n; 65 n++; 66 for(i=pos;i>=1;--i){ 67 int ii=i; 68 while(ii>0){ 69 tmp=ii%10; 70 ii=ii/10; 71 cnt++; 72 if(cnt==n){ 73 res=tmp; 74 break; 75 } 76 } 77 if(res!=-1) break; 78 } 79 printf("%d\n",res); 80 }else if(n-(int)haha[pos]==0){ 81 printf("%d\n",pos%10); 82 } 83 } 84 } 85 return 0; 86 }