UVA 10706 Number Sequence
传送门:https://vjudge.net/problem/UVA-10706
题意:
112123123412345123456123456712345678……一直排下去问第i(i<2147483647)个数字是什么。
题解:
开始学二分的时候没做出来,最近练习二分的时候想起来了。。。。。
我们可以先打个表看看2147483647大致在什么地方,发现其实它是小于1e5的。。所以就先拿个sum数组记录一下每个数结束时是第几个数字,同时又拿一个pos记录下123456……中每个数的位置。
这两个前缀和处理好了之后就很简单了,两次二分就可以了。先二分是以哪个数结尾,再二分找处于哪个数的位置,将找到的那个数化成字符串输出下目标位置就ac了。(其实因为最长是以1e5的位置结束的,所以可以两次O(n)暴力的,是我强行二分了。。。。貌似还有其他二分的方法。)
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e5+100; 4 long long T,n,sum[maxn],pos[maxn]; 5 6 void init() { 7 sum[0]=0; sum[1]=1; sum[2]=3; 8 pos[0]=0; pos[1]=1; pos[2]=2; 9 for(int i=3;i<=100000;++i) { 10 int w=0,x=i; 11 while(x){ 12 x/=10; w++; 13 } 14 sum[i]=sum[i-1]+pos[i-1]+w; 15 pos[i]=sum[i]-sum[i-1]; 16 } 17 } 18 int solve(long long n) { 19 int p=lower_bound(sum,sum+100000,n)-sum; 20 n-=sum[p-1]; 21 p=lower_bound(pos,pos+100000,n)-pos; 22 n-=pos[p-1]; 23 stringstream ox; string s; 24 ox << p; ox >> s; 25 return s[n-1]-'0'; 26 } 27 int main() { 28 init(); 29 scanf("%d",&T); 30 while(T--) { 31 scanf("%lld",&n); 32 printf("%d\n",solve(n)); 33 } 34 return 0; 35 }
沉迷于日日菜醒,不能自拔
posted on 2017-08-21 21:25 仰望咸鱼Orzzzz 阅读(276) 评论(0) 编辑 收藏 举报