博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

ZOJ_1410 Number Sequence (2002年ACM亚洲区一道竞赛题)

Posted on 2010-08-14 21:14  还好  阅读(2237)  评论(0编辑  收藏  举报
Number Sequence

Time Limit: 1 Second      Memory Limit: 32768 KB

A single positive integer i is given. Write a program to find the digit located in the position i in the sequence of number groups S1S2...Sk. Each group Sk consists of a sequence of positive integer numbers ranging from 1 to k, written one after another.

For example, the first 80 digits of the sequence are as follows:

11212312341234512345612345671234567812345678912345678910123456789101112345678910


Input

The first line of the input file contains a single integer t (1 <= t <= 10), the number of test cases, followed by one line for each test case. The line for a test case contains the single integer i (1 <= i <= 2147483647)


Output

There should be one output line per test case containing the digit located in the position i.


Sample Input

2
8
3


Sample Output


2
2

此道题是Asia 2002, Tehran (Iran), Iran Domestic 一道竞赛题,ACM比赛的时候总时间是五个小时,题目好像一共有八道题,貌似我做这个题目的用时已经超过了五个小时^_^.坐下来的感觉确实还是相当的有点难度的,表面上看起来的题目貌似挺简单的,但真真实现起来的时候还真的不知如何下手!感兴趣的不妨试试!

我的思路是这样子的:先看数据的规律:

1

12

123

1234

12345

。。。

 

其实就是在上一个数的最后一个数(不是最后一位)加1得到下一个数,我的想法是定义一个数组nums[32000],用来保存每个数的长度!比如1的长度是1,12的长度是2,以此类推。。。.这样总的长度就是这些所有数的长度之和!所以要找第n位的数字,首先是先判断n落在数组nums[32000]哪个区间里(可以参看下面代码中的方法Find(int* nums, int n, int dig))!假如n是落在nums[10]里面,那么问题就转化成在nums[10]里面找第n-(nums[0]+nums[1]+...+nums[9])位是数字几了!其实也就是在类似于这样的数字12345678910111213...里面寻找了!这个时候问题就相对简单一点了!这个可以参考下面代码中的Find(int dig)方法,我就不多说了!

下面是我的C++代码,Run Time:0MS, Run Memory:184KB

 

代码
#include<iostream>
using namespace std;

int a[4]={9,180,2700,36000};

int Power(int i, int j)
{
    
int total=1;
    
for(int k=1;k<=j;k++)
    {
        total
*=i;
    }
    
return total;
}

int Find(int dig)
{
    
int i;
    
for(i=0;i<4;i++)
    {
        
if(dig<=a[i])break;
        dig
-=a[i];
    }
    
int number=dig/(i+1);
    
int place=dig%(i+1);
    
if(place==0)
    {
        number
+=Power(10,i)-1;
        
return number%10;
    }
    
else
    {
        number
+=Power(10,i);
        
int count=i+1-place+1;
        
while(count>1)
        {
            number
/=10;
            count
--;
        }
        
return number%10;
    }
}

int Find(int* nums, int n, int dig)
{
    
int i=0;
    
for(i=0;i<n;i++)
    {
        
if(dig<=nums[i])break;
        dig
-=nums[i];
    }
    
return Find(dig);    
}


int main(void)
{

    
int* nums = new int[32000];

    nums[
0= 1;

    
double total = nums[0];

    
for (int i = 1; i < 32000; i++)
    { 
        
if (total >= 2147483647break;
        
if(i<=9-1)
        {
            nums[i] 
= nums[i-1]+1;
        }
        
else
        {
            
if(i<=90+9-1)
            {
                nums[i] 
= nums[i-1]+2;
            }
            
else
            {
                
if(i<=90+9+900-1)
                {
                    nums[i] 
= nums[i-1]+3;
                }
                
else
                {
                    
if(i<=90+9+900+9000-1)
                    {
                        nums[i] 
= nums[i-1]+4;
                    }
                    
else
                    {
                        nums[i] 
= nums[i-1]+5;
                    }
                }
            }
        }
        total 
+= nums[i];
    }
    
int t,dig;
    cin
>>t;
    
while(t>0)
    {
        cin
>>dig;
        cout
<<Find(nums,32000,dig)<<endl;
        t
--;
    }
    
return -1;
}