题目描述
给出一个正整数i。编写一个程序来查找位于编号组S1S2 ... Sk序列中位置i的数字。每组Sk由一系列从1到k的正整数组成,依次写入。
例如,序列的前80位数字如下:
11212312341234512345612345671234567812345678912345678910123456789101112345678910
例如,序列的前80位数字如下:
11212312341234512345612345671234567812345678912345678910123456789101112345678910
输入
输入文件的第一行包含一个整数t(1≤t≤10),即测试用例的数量,每个测试用例后跟一行。测试用例的行包含单个整数i(1≤i≤2147483647)
输出
每个测试用例应该有一个输出行,其中包含位于位置i的数字。
样例输入
2
8
3
样例输出
2
2
思路:模拟分组,把 1 看做第 1 组,12 看做第 2 组,123 看做第 3 组……那么第 i 组就是存放数字序列为 [ 1,i ] 的正整数,但第 i 组的长度不一定是 i
已知输入查找第 n 个位的 n 的范围为 (1 ≤ n ≤ 2147483647 ),那么至少要有 31268 个组才能使得数字序列达到有第 2147483647 位
注意:2147483647 刚好是 int 的正整数最大极限值( ),所以对于 n 用 int 定义就足矣。但是 pos [ 31268 ] 存在超过 2147483647 的位数,因此要用 unsigned 或 long long 之类的去定义 pos [ ]
#include <iostream>
#include <cmath>
using namespace std;
int n;
long long len[40000];//记录第i个串的长度
long long pos[40000];//记录第i个串开始位置的下标
int large[1200000];//记录最长的串
int main()
{
len[1]=pos[1]=1;
for(int i=2;i<40000;i++)
{
len[i]=len[i-1]+(int)log10(i*1.0)+1;/*(int)log10(i*1.0)+1
是求串 1 12 123 ....112...9.10.11....后序列比前序列多出的数
的位数,超过10以后会多一位或者更多,所以用log10()求解*/
pos[i]=pos[i-1]+len[i-1];
}
int cnt=1;
for(int i=1;i<40000;i++)//找到40000的目的是 找到最大序列(上文的串)
{
int bit[100];
int k=i,num=0;
while(k)/*将k取余放入数组bit中,但此时序列表示数的所在的位置
是反着的,故用large转置回来 */
{
bit[num++]=k%10;
k/=10;
}
while(num--)
{
large[cnt++]=bit[num];
}
}
int t;
cin>>t;
while(t--)
{
cin>>n;
int i;
for(i=1;i<40000;i++)
{
if(pos[i]>=n)//找到所求第n个数在第几个序列里
break;
}
if(pos[i]==n)//如果那个数刚好是序列开头的第一位数输出1
cout<<1<<endl;
else
cout<<large[n-pos[i-1]+1]<<endl;//否则输出的数 从large中找
}
return 0;
}