acm pku 1019 Number Sequence的遞歸計算方法

Number Sequence

Description

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

Source

Tehran 2002, First Iran Nationwide Internet Programming Contest

 

       這道題目其實就是一道數學歸納題,用遞歸方法可以求得其結果,爲此需要如下參數:

Len[N]:表示第一次出現數字N(而不是字符串N)時,數字序列的長度。

執行結果:

Calc[N]:表示數字序列123…N的數字個數。

對這道題目必定有:

 

假設要求的數字序列的第N個數字idata時,其算法如下:

Step 1: 求出小於等於2147483647的所有Len以及相應的Calc

Step 2: 尋找Len[i]使得Len[i]<=N<Len[i+1];

       Len[i]=N,則idata=i%10; 算法結束。

       否則(Len[i]<N<Len[i+1]), N-=Len[i]

Step 3: 尋找Calc[i]使得Calc[i]<=N<Len[i+1];

       Calc[i]=N,則idata=i%10;算法結束。

       否則(Calc[i]<N<Calc[i+1])N-=Len[i], idata = i+1的第N位數;算法結束。

具體實現如下:

#include "iostream"

#include "math.h"

using namespace std;

 

const int N = 100000;

unsigned int Len[N];

unsigned int Calc[N];

 

void LenAndLen(void)

{

       int i = 1;

 

       Len[1] = 1;

       Calc[1]= 1;

       while(Len[i++] < 2147483647)

       {

              Calc[i] = Calc[i-1] + (int)floor(log10((double)i) + 1.0);

              Len[i]  = Len[i-1]  + Calc[i];

       }

}

 

int SearchData(unsigned int N)

{

       int i = 1;

      

       while(Len[i] < N)

       {

              i++ ;

       }

       if(N == Len[i])

       {

              return i%10;

       }

       else

       {

              N -= Len[i-1];

              i = 1;

              while(Calc[i] < N)

              {

                     i++ ;

              }

              if(N == Calc[i])

              {

                     return i%10;

              }

              else

              {

                     N -= Calc[i-1];

                     return i/((int)pow(10., (double)((int)log10((double)(i*10)))-N))%10;

              }

       }

}

 

int main(void)

{

       unsigned int t, n;

 

       LenAndLen();

       cin >> t;

       while(t --)

       {

              cin >> n;

              cout << SearchData(n) << endl;

       }

       return 0;

}

 

Problem: 1019

 

User: uestcshe

Memory: 496K

 

Time: 16MS

Language: C++

 

Result: Accepted

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章