Number Sequence
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 39182 | Accepted: 11366 |
Description
A single positive integer i is given. Write a program to find the digit located in the position i in the sequence of number groups S1S2...Sk. Each group Sk consists of a sequence of positive integer numbers ranging from 1 to k, written one after another.
For example, the first 80 digits of the sequence are as follows:
11212312341234512345612345671234567812345678912345678910123456789101112345678910
For example, the first 80 digits of the sequence are as follows:
11212312341234512345612345671234567812345678912345678910123456789101112345678910
Input
The first line of the input file contains a single integer t (1 ≤ t ≤ 10), the number of test cases, followed by one line for each test case. The line for a test case contains the single integer i (1 ≤ i ≤ 2147483647)
Output
There should be one output line per test case containing the digit located in the position i.
Sample Input
2 8 3
Sample Output
2 2
一个序列1 12 123 1234 12345 123456 1234567 12345678 123456789 12345678910 1234567891011 ---------
空格是为了明显分组概念的
问题是求第n个数的数字是什么
就是一位数
关键点
1.一个数的位数可以用对数求 例如 10:log10(10)+1 = 2,1:log(1)+1 = 1;
(注 求大数阶乘的位数也可以用对数
2.关于函数的重载以及类型转换
double log(double)
float log(float)
double pow(double , double)
float pow(float ,float)
具体见代码 (主要是理解分组概念/一个数字位的log10对数的应用)
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
#define For(i,a,b) for(i=a;i<=b;i++)
#define Out(x) cout<<x<<endl
#define ll long long
const ll inf = 40000;
ll num[inf];
ll sum[inf];
void reset()
{
sum[0]=0;
num[1]=1;
sum[1]=1;
int i;
For(i,2,inf)
{
num[i]= num[i-1] + (ll)log10((double)i)+1; ///以1开头为一组,第i组数共多少位数字
sum[i] = num[i] + sum[i-1]; ///前i组的序列长度
}
}
ll digit2(ll n) ///两个digit函数大致相同
{ ///区别 len大于/小于pos
int i;
ll len,pos;
For(i,1,inf)
{
if(sum[i] >= n) ///等于的时候会出现pos=0
{ ///当sum[i] == n 时 需要跳出 否则会出现len>pos
break;
}
}
pos = n-sum[i-1]; ///pos表示在第i组中的位置
len=0;
if(pos <= 9) ///小技巧 1~9 直接打印,都是个位数
{
return pos;
}
For(i,1,inf)
{
len+=(ll)log10((double)i)+1; ///在第i组中的长度
if(len+(ll)log10((double)(i+1))+1 >= pos) ///当找到比pos大于等于的i后跳出
{
break;
}
}
int x = (ll)log10((double)(i+1))+1-(pos-len); ///此处与digit不同
return ((i+1)/(ll)pow(10.0,x))%10;
///类比下面的digit函数
///假设:序列为--123124125--
///那么len在pos前123 3位置
///pos在124 2位置
///则此时是i=123 i+1=124
///x是需要截取的数字的位数 需要把124的4去掉后取余
///即除以10的(124(i+1)的数字长度)-(pos-len))次方 (例x=1)
///主要是判断到底i在哪 pos位置指向哪个数字
}
ll digit(ll n)
{
int i;
ll len,pos;
For(i,1,inf)
{
if(sum[i] >= n) ///等于的时候会出现pos=0
{
break;
}
}
pos = n-sum[i-1];
///pos在第i组的位置 因为上if判断所以避免了出现pos=0
len=0;
for(i=1; len<pos; i++)
{
len+=(ll)log10((double)i)+1;
}
int x = len-pos;
return ((i-1)/(ll)pow((double)10.0,x))%10;
///假设:序列为--122123124--
///len在123 3位置
///pos在123 2位置
///则此时是i=124 i-1=123
///x是需要截取的数字的位数 需要把123的3去掉后取余
///即除以10的len-pos方(例x=1)
///主要是判断到底i在哪 pos位置指向哪个数字
}
int main()
{
reset();
ll t,n;
cin>>t;
while(t--)
{
cin>>n;
Out(digit(n));
}
return 0;