UVA - 10706 Number Sequence

来源:互联网 发布:推荐淘宝包包店铺 编辑:程序博客网 时间:2024/05/18 01:26

题目大意:    有一个数组 s[1] = 1 , s[2] = 1 2 , .......s[k] = 1....k,要求给定一个n表示数组的第几位,要求这个第几位是什么数。例如 n为1 时候是1 n为 2 时候是1 ,n 为3 时候为2


解题思路:    1:思路:预处理打表+查找
                     2:题目给的数据可以发现一些规律
                        s[1]:1                                   总位数1
                        s[2]:1 2                                总位数1+2 = 3
                        s[3]:1 2 3                             总位数1+2 +3 = 6
                        .
                        .
                        .
                        s[9]:1 2 3 4 5 6 7 8 9          总位数1+2 +3+...+9 = 45
                        s[10]:  1 2 3 4 5 6 7 8 9 10    总位数45+1+2 +3+...+9 +1+0 = 56
                        s[K]:1 2 3 4 . . . . . . k           总位数 num[k-1]+1+2+......
                                               用num[k]保存当值为k时候总的位数.
                      所以我们要是能够预先把所有的数据全部求出弄成一张表,然后输入的时候直接查找位于那个位置,然后在去查找这个位置 ,由于上面的递增趋势,我么可以推断当k到100000时候就会超过int,所以开个这么大的数组就可以了。
                     3:打表过程:我么采用枚举当前值的位数,例如位数为1,那么就有1-9共9位数,如果位数为2就有10-99公共90个.......假设当前的数值为n,那么根据上面的规律求出num[n],一次这样求出所以数据
                     4:查找,O(n)的时间复杂度,只要找到num[i-1] < n, num[i]>=n , 那么我们可以知道这个数存在s[n]中,把n减去num[i-1],可以知道要求的数在s[n]中第几位,然后再去一一判断。注意这里n可能为1234等多位数,那么要把他拆开,这时候是先拆前面即最大位。
                     5注意事项:由于这一题的n最大为2147483647,那么我们开得num数组要为long long,中间的一些处理也要为long long不然会有精度缺失


#include <cstdio>#include <cmath>int main() {long long T, A[32000] = {0}, B[32000] = {0};scanf("%lld", &T);for (int i = 1; i < 32000; i++) {A[i] = A[i-1] + log10(i) + 1; B[i] = B[i-1] + A[i];}while (T--) {long long i, n, temp;scanf("%lld", &n);for (i = 0; B[i] < n; i++); temp = n - B[i-1];for (i = 0; A[i] < temp; i++);temp = A[i] - temp;while (temp--) i /= 10;printf("%lld\n", i % 10);}return 0;}


0 0