标签:
大致题意:
有一串数字串,其规律为
1 12 123 1234 12345 123456 1234567 12345678 123456789 12345678910 1234567891011 123456789101112······k
输入位置n,计算这一串数字第n位是什么数字,注意是数字,不是数!例如12345678910的第10位是1,而不是10,第11位是0,也不是10。总之多位的数在序列中要被拆分为几位数字,一个数字对应一位。
解题思路:
模拟分组,把1看做第1组,12看做第2组,123看做第3组……那么第i组就是存放数字序列为 [1,i]的正整数,但第i组的长度不一定是i
已知输入查找第n个位的n的范围为(1 ≤ n ≤ 2147483647),那么至少要有31268个组才能使得数字序列达到有第2147483647位
注意:2147483647刚好是int的正整数最大极限值( ),所以对于n用int定义就足矣。但是s[31268]存在超过2147483647的位数,因此要用unsigned 或long 之类的去定义s[]
其中数学难点有2:
这两个数学规律在纸上计算一下就能找出来
(int)log10((double)i)+1
(i-1)/(int)pow((double)10,len-pos)%10
解题思路参考:http://blog.csdn.net/lyy289065406/article/details/6648504
1 #include <cstdio> 2 #include <cmath> 3 //数组的长度是根据题目给出的i的范围计算出来的 4 #define LEN 31269 5 //nnum[i]表示第i组数字序列的长度 6 long nnum[LEN]; 7 //anum[i]表示前i组数字序列的长度 8 long long anum[LEN]; 9 10 //打表,计算出第i组序列的情况 11 void init() 12 { 13 nnum[0] = anum[0] = 0; 14 for(int i = 1; i <= LEN; ++i) 15 { 16 nnum[i] = nnum[i-1] + (long)log10((double)i) + 1; 17 anum[i] = anum[i-1] + nnum[i]; 18 } 19 return ; 20 } 21 //寻找第n位数字所在的组 22 int check(int n) 23 { 24 int i = 1; 25 while(n > anum[i]) 26 ++i; 27 //因为n>anum[i],所以这里i-1就是n所在那组之前的那一组的位置 28 return --i; 29 } 30 31 int main() 32 { 33 int t; 34 init(); 35 scanf("%d",&t); 36 while(t--) 37 { 38 int n,i; 39 scanf("%d",&n); 40 //x就是n所在那组之前的那一组的下标 41 int x = check(n); 42 //anum[x]极速hi前x组的数字序列长度,n-anum[x]则是n所在那一组中第n位的数字所在的位置 43 int cnt = n - anum[x]; 44 int len=0; 45 for(i = 1; len < cnt; ++i) 46 len += (int)log10((double)i)+1; 47 48 printf("%d\n",(i-1) / (int)pow((double)10, len - cnt) % 10); 49 } 50 return 0; 51 }
标签:
原文地址:http://www.cnblogs.com/guoyongheng/p/5747452.html