思路:
通过观察可以发现,可以把从1开始的数分成一组,可以观察出在数列中数的总数为(1+n)*n/2,其中n为组数,在通过与判断所在的组数进行求解,这是我在看到题目的最初的想法。而在题目中因为所判断的是在该位置的单个数而非该数据大小,即如11212312341234512345612345671234567812345678912345678910中55个位置的数据是1而不是10.所以在原思路的基础上进行调整,并通过二分查找,输出所求的结果。
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#define ll long long
using namespace std;
ll q, k, l, r, mid, ans;
ll solve(ll x){
ll pow = 1, sum = 0, a = 0, n = 0, d = 0;
while (true) {
pow *= 10; d++;
if (x > pow - 1) {
n = pow - pow / 10;
sum += (a + d)*n + n * (n - 1) / 2 * d;
a += n * d;
}
else {
n = x - pow / 10 + 1;
sum += (a + d)*n + n * (n - 1) / 2 * d;
break;
}
}
return sum;
}
int main() {
cin >> q;
while (q--) {
cin >> k;
l = 0; r = 1e9;mid=0;
while (l <= r) {
mid = (l + r) >> 1;
if(solve(mid)>=k) r=mid-1;
else l = mid + 1,ans=mid;
}
k=k-solve(ans);
ll m=1,len=0,n=0,y=0,sum=0;
while(k)
{
m*=10;
n=m-m/10;
len++;
if(k>n*len)
{
sum+=n;
k-=n*len;
}
else
{
sum+=k/len;
y=k%len;
break;
}
}
if(y==0) printf("%lld\n",sum%10);
else
{
sum+=1;
while(len!=y)
{
len--;
sum/=10;
}
printf("%lld\n",sum%10);
}
}
return 0;
}