数字序列 Number Sequence

题目描述

给出一个正整数i。编写一个程序来查找位于编号组S1S2 ... Sk序列中位置i的数字。每组Sk由一系列从1到k的正整数组成,依次写入。 
例如,序列的前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;
 } 


猜你喜欢

转载自blog.csdn.net/qq_41486817/article/details/80670979