题目大意:有这样一串序列11212312341234512345612345671234567812345678912345678910123456789101112345678910…,问第i个位置数的值。
这里涉及到了二分这个蜜汁问题,那我百度了以下,贴一下二分的不同写法:
越大越好时:
while(r>l){mid=(l+r)/2…}
然后更新是不符合条件l=mid+1,否则是r=mid
越小越好时:
while(r>l){mid=(l+r+1)/2…}
然后更新是符合条件l=mid,否则是r=mid-1
代碼:
#include<cstdio>
#include<cmath>
#include<cstring>
int p;
long long sum[33000];
char buf[150000];
char temp[10];
char* join(int q) {
int c=0, t=q;
while(q) {
c++;
q/=10;
}
temp[c--]=0;
while(t) {
//拆解每一位
temp[c--]=t%10+'0';
t /= 10;
}
return temp;
}
int findp(long long a) {
//找到一個值,他第一次出現的位置小於或等於a
//如果小於a說明a不是一個值的第一次出現位置,會返回一個值
//這個值第一次出現的位置是接近a的,字符串的長度其實是按順序lleijia
//下去的,所以所求位置減去這個數第一次出現的位置,相當與剪掉了前面
//冗餘的部分,差值所指向的位置就是一個累加串這個位置的值
int l=0, r=32000;
int mid;
while(l<r) {
mid=(l+r+1)/2;
if(sum[mid]>=a) r=mid-1;
else l=mid;
}
return l;
}
int main() {
int t, k, i;
buf[0]='0';
sum[0]=0ll;
for(i=1; i<=32001; i++) {
strcat(&buf[strlen(buf)], join(i));
sum[i] = sum[i-1]+strlen(buf)-1;
}
scanf("%d", &t);
while(t--) {
scanf("%d", &k);
printf("%c\n", buf[k-sum[findp(k)]]);
}
return 0;
}