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;
}