Question:http://poj.org/problem?id=1019
问题点:打表。
1 Memory: 392K Time: 16MS
2 Language: C++ Result: Accepted
3
4 #include <iostream>
5 #include <cmath>
6 using namespace std;
7
8 #define uint unsigned int
9 uint table[31269];
10 uint a[6] = {0,1,11,111,1111,11111};//(1-10^k)/(1-10)的对应结果
11 uint b[6] = {0,9,189,2889,38889,488889};//[1...j]中位数变动边界值。如9 10,从个位到十位时记录9的偏移量
12 int getLen(int n)
13 {
14 if(n<10) return 1;
15 else if(n<100) return 2;
16 else if(n<1000) return 3;
17 else if(n<10000) return 4;
18 else return 5;
19 }
20 int main()
21 {
22 uint i=1,seg;
23 memset(table,0,sizeof(table));
24 for(i = 1,seg = 0;i<31269;i++)//打表
25 {
26 seg += getLen(i);
27 table[i] = table[i-1] + seg;
28 }
29 uint eg,num,j,k,bit;
30 cin>>eg;
31 while(eg--)
32 {
33 cin>>num;
34 //if(num==0) break;
35 for(j=1;j<i&&num>table[j];j++);//对应段[1...j]的最大数j
36 num -= table[j-1];//num在[1...j]中的偏移量
37 for(k=1;num>b[k];k++);//num所在数字有几位:如 num偏移为12,所在数字为11,长度k=2
38 //下面的两个公式简单说明一下:
39 //如 j=101:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ... 100 101
40 //当所在数字(同上面注释里的所在数字)n=19时,偏移量 offset = 19 + (19-9) ,即个位数字数 + 十位数字数
41 //所以,当n的长度为k时,offset = n + (n-9) +(n-99) +...+(n-(k-1个9)) =k(n+1) -(1+10+100+...+10^(k-1))=k(n+1)-(1-10^k)/(1-10)
42 //(1-10^k)/(1-10)已存到数组a中,则offset = k(n+1) - a[k],下面两个公式都是依此推导
43 bit = (num + a[k] - k - 1)%k;//计算num在 所在数字的位置 :如num为13指向所在数字12的十位,则bit=0(bit从数字高位到低位递增)
44 num = (ceil(double(num + a[k])/k-1));//计算num的所在数字的值
45 char buf[10];
46 sprintf_s(buf,"%d",num);
47 cout<<buf[bit]<<endl;//数字转字符串,输出指定位置字符
48 }
49 //system("pause");
50 return 0;
51 }