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: 11212312341234512345612345671234567812345678912345678910123456789101112345678910Input
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 3Sample Output
2 2Source
Tehran 2002, First Iran Nationwide Internet Programming Contest题意:
112123123412345......这样的数列输出第n(1<=n<=2147483647)个数字,数字,数字。
思路:
有很多人认为输出数,我没被坑到,但也不会做。
先给出思路来源。
首先一个数组记录每组长度,另一个记录1~2,1~3组......的长度(有部分数据会超int),这步打表就行了。
经过百度知道数列中最大的数为31268(根据n最大范围),那么数组需要的内存就知道了,因为:
1组:1
2组:12
3组:123
......
31268组:123......31268
对于每个数的长度可以使用普通for循环去完成,但我看到更方便的方法:log10(i)+1,例如:log10(1)+1=1......log10(10)+1=2......log10(100)+1=3......
这样取位数是不是很快啊,数据的处理完成了,接下来就是输出了。
寻找范围,类比b[i]=b[i-1]+a[i](数组含义请看代码),n=b[i-1]+k(k为所求第n个数字所在的区间位置,类似a[i]),那么又类似a[i]=a[i-1]+log10(i)+1求出i(i为所求的数字所在的数,例如2016中我们要找的是1)k~l第n个数字所在的区间,最后运用i/(int)pow(10,l-k)%10求出答案。
下面给出n,k,l,i以及结果,通过这些也许能知道i/(int)pow(10,l-k)%10的原理:
case 1:
n=225478
k=721 l=723 i=277
ans=2
case 2:
225479
722 723 277
7
case 3 :
225480
723 723 277
7
case 4:
225481
724 726 278
2
希望对大家的思路有所帮助。
示例程序
Source Code Problem: 1019 Code Length: 554B Memory: 752K Time: 16MS Language: GCC Result: Accepted #include <stdio.h> #include <math.h> int main() { int i,i1,t,n,a[31269],k,l; //a[]为每组数据的长度,b[]为1~2,1~3组...的数据长度 long long b[31269]; //有几组数据超出了int,就用了long long a[1]=1; //开始初始化 b[1]=1; for(i=2;31269>i;i++) { a[i]=a[i-1]+log10(i)+1; //这里可以写成a[i]=a[i-1]+log10(i*10),但乘法效率比加法低 b[i]=b[i-1]+a[i]; } scanf("%d",&t); for(i=1;t>=i;i++) { scanf("%d",&n); i1=1; while(n>b[i1]) { i1++; } k=n-b[i1-1]; //这里不容易理解可以通过b[i]=b[i-1]+a[i]来理解,n=b[i1-1]+k l=0; for(i1=1;l<k;i1++) //这也可以从初始化来类比 { l=l+log10(i1)+1; } printf("%d\n",(i1-1)/(int)pow(10,l-k)%10); //pow返回的是double,要强制转化,log也是double,貌似不受影响,这里稍微提醒一下 } return 0; }