多余的话不说了,代码注释挺详细的,把别人的修改了,我自己还真不咋会。那个公式应该很容易理解,1到9,每组比上一组多1位,10到99多2位。。这32MS我就不知道咋回事了,第一次交还是0MS的。。
#include<iostream>
#include<cmath>
using namespace std;
unsigned s[31270],a[31270]; //s[i]用来保存从第一组数到第i组总共多少位。
//a[i]用来保存第i组数比i-1组长了多少。后来直接接s[i]上。
void reset() //这个就是来打表,先保存好再输出
{
int i;
a[1] = 1;
s[1] = 1;
for(i = 2; i< 31270; i++)//为什么是31720,因为一共是2147483647位,第一组是1位,//第二组是2位,在第31720组会填满2147483647位数。
{
a[i] =a[i-1] + (int)log10((double)i) + 1; //每一组数字都比上一组长//(int)log10((double)i) + 1
s[i] =s[i-1] +a[i];
}
}
/* 计算 */
int work(int n)
{
int i = 1;
int length = 0;
/* 找到 n 所在的组 */
while (s[i] < n) i++;
/* n 在该组的下标 */
int pos = n - s[i-1];
/* length: n指向的数字的最后一位的下标 */
for (i = 1; length < pos; i++)
{
length += (int)log10((double)i) + 1;
}
/* 去掉所求位后面的数字然后取余*/
/* i: n指向的数字 + 1 */
return ((i-1) / (int)pow((double)10, length - pos)) % 10;
}
int main()
{
int t;
unsigned int n;
reset();
cin >> t;
while(t--)
{
cin >> n;
cout << work(n) << endl;
}
return 0;
}
![](https://img-my.csdn.net/uploads/201209/28/1348846383_1268.jpg)