poj 1019 打表数列

题目大意:

有一串数字串,其纪律为

1 12 123 1234 12345 123456 1234567 12345678 123456789 12345678910 1234567891011 123456789101112······k

输进地位n,打算这一串数字第n位是什么数字,留心是数字,不是数!例如12345678910的第10位是1,而不是10,第11位是0,也不是10。总之多位的数在序列中要被拆分为几位数字,一个数字对应一位。

解题思路:  (1)    1                                         s[1]=1;

                 (2)     12                                       s[2]=2;

                 (3)     123                                     s[3]=3; 

                 ............

                 (9)     123456789                          s[9]=9;  

                 (10)    12345678910                      s[10]=10;

                  ...................

           首先将长数列分成如上所示部分,  建立一个数组,保存每组数列的位数即s[n]=m;

           同时建立一个数组sum[],用来保存 所有位数和;

根据代码详解:

#include <iostream>
#include <cmath>

using namespace std;

long long int s[32000], sum[32000];//大数位用 long long int;由于给定的数字是 i (1 ≤ i ≤ 2147483647)正好是int的最大位数,所以用32000的数组足以存下

void playtable()//打表
{
int i;
s[1] = 1;
sum[1] = 1;
for(i = 2; i < 32000; i++)
{
s[i] = s[i-1] + (int)log10(1.0*i) + 1;//(int)log10(1.0*i) 是用数学方法求数位,很。。。
sum[i] = sum[i-1] + s[i];
}
}

int table(int n)
{
int i = 1;
int length = 0;

while (sum[i] < n) i++;

int pos = n - sum[i-1];//pos 表示的是所求的数在第i组 的第位上;
for (i = 1; length < pos; i++)
{
length += (int)log10(1.0*i) + 1;求出这个i组到pos位的长度
}


return ((i-1) / (int)pow(1.0*10, length - pos)) % 10;

i  表示的是第几个数;

length - pos 表示剩余数长度;


}

int main()
{
int t;
long long int n;
playtable();
cin >> t;
while(t--)
{
cin >> n;
cout << table(n) << endl;
}
return 0;
}

       

原文地址:https://www.cnblogs.com/lfyy/p/2725984.html