POJ1019

轉載請註明出處:優YoU http://user.qzone.qq.com/289065406/blog/1301527312ios

大體題意:函數

有一串數字串,其規律爲spa

1 12 123 1234 12345 123456 1234567 12345678 123456789 12345678910 1234567891011 123456789101112······kcode

輸入位置n,計算這一串數字第n位是什麼數字,注意是數字,不是數!例如12345678910的第10位是1,而不是10,第11位是0,也不是10。總之多位的數在序列中要被拆分爲幾位數字,一個數字對應一位。blog

 

解題思路:ci

首先建議數學底子很差的同窗,暫時放一放這題,太過技巧性了,連理解都很困難get

 

模擬分組,把1看作第1組,12看作第2組,123看作第3組……那麼第i組就是存放數字序列爲 [1,i]的正整數,但第i組的長度不必定是i原型

 

已知輸入查找第n個位的n的範圍爲(1 ≤ n ≤ 2147483647),那麼至少要有31268個組才能使得數字序列達到有第2147483647位數學

 

注意:2147483647恰好是int的正整數最大極限值( ),因此對於n用int定義就足矣。可是s[31268]存在超過2147483647的位數,所以要用unsigned 或long 之類的去定義s[]io

 

詳細的解題思路請參照程序的註釋。

其中數學難點有2:

(int)log10((double)i)+1

(i-1)/(int)pow((double)10,len-pos)%10

很是技巧性的處理手法,其意義已在程序中標明

 

 

另外要注意的就是log()和pow()函數的使用

兩個都是重載函數,函數原型分別爲

double log(double)

float log(float)

double pow(double , double)

float pow(float ,float)

因此當傳參的類型不是double或float時,必須強制轉換爲其中一種類型,不然編譯出錯。通常建議用double

//Memory Time   
02.//476K    0MS   
03.  
04.#include<iostream>  
05.#include<math.h>  
06.using namespace std;  
07.  
08.const int size=31269;  
09.  
10.unsigned a[size];   //a[i] 表示第i組數字序列的長度  
11.unsigned s[size];   //s[i] 表示前i組數字序列的長度  
12.                     //第i組存放的數字序列爲 [1,i]的正整數,但第i組的長度不必定是i  
13.                     //例如數字13要被看作1和3兩個位,而不是一個總體  
14.  
15./*打表,預先獲取第2147483647個位的序列分組狀況*/  
16.  
17.void play_table(void)  
18.{  
19.    a[1]=s[1]=1;  
20.    for(int i=2;i<size;i++)  
21.    {  
22.        a[i]=a[i-1]+(int)log10((double)i)+1;  //log10(i)+1 表示第i組數字列的長度 比 第i-1組 長的位數  
23.        s[i]=s[i-1]+a[i];      //前i組的長度s[i] 等於 前i-1組的長度s[i-1] + 第i組的長度a[i]  
24.    }                          //log()是重載函數,必須對int的i強制類型轉換,以肯定參數類型  
25.    return;  
26.}  
27.  
28./*計算序列第n個位置上的數字*/  
29.  
30.int compute(int n)  
31.{  
32.    int i=1;  
33.    while(s[i]<n)  
34.        i++;    //肯定整個數字序列的第n個位置出如今第i組  
35.  
36.    int pos=n-s[i-1];   //pos爲 整個數字序列的第n個位置 在 第i組中的下標值  
37.  
38.    int len=0;  
39.    for(i=1;len<pos;i++)  //從第1組開始遍歷第i前的每個組,利用log10(i)+1遞推第i組的長度  
40.        len+=(int)log10((double)i)+1;  //len爲第i組(n所在的組)的長度  
41.  
42.    return (i-1)/(int)pow((double)10,len-pos)%10;    
43.           //之因此i-1,是由於前面尋找第i組長度時,i++多執行了一次  
44.           //i=i-1 此時i恰好等於第n位個置上的數 (數是總體,例如123一百二十三,i恰好等於123,但n指向的多是1,2或3)  
45.           //pos爲n指向的數字在第i組中的下標值  
46.           //len爲第i組的長度  
47.           //那麼len-pos就是第i組中pos位置後多餘的數字位數  
48.           //則若要取出pos位上的數字,就要利用(i-1)/pow(10,len-pos)先刪除pos後多餘的數字  
49.           //再對剩下的數字取模,就能夠獲得pos  
50.           //例如要取出1234的2,那麼多餘的位數有2位:34。那麼用1234 / 10^2,獲得12,再對12取模10,就獲得2  
51.  
52.}          //pow()是重載函數,必須對int的i強制類型轉換,以肯定參數類型  
53.  
54.int main(void)  
55.{  
56.    play_table();  
57.  
58.    int test;  
59.    cin>>test;  
60.    while(test--)  
61.    {  
62.        int n;  
63.        cin>>n;  
64.        cout<<compute(n)<<endl;  
65.    }  
66.    return 0;  
67.}  
相關文章
相關標籤/搜索