OJ 洛谷 P1028 數的計算

2021-10-03 22:04:34 字數 2408 閱讀 5869

我們要求找出具有下列性質數的個數(包含輸入的自然數n

nn):

先輸入乙個自然數n

nn(n

≤1000

n\leq1000

n≤1000

),然後對此自然數按照如下方法進行處理:

不作任何處理;

在它的左邊加上乙個自然數,但該自然數不能超過原數的一半;

加上數後,繼續按此規則進行處理,直到不能再加自然數為止.

自然數n

nn,且n

≤1000

n\leq1000

n≤1000

1個整數,表示具有該性質數的個數

輸入

輸出

解釋:滿足的數分別為6,16,26,126,36,136

顯然,最簡單直接的做法就是遞迴(將乙個大問題規約成更小規模的子問題,通過子問題的求解完成原問題)

假設:當輸入為4時,滿足的其性質的數有——4本身,加上其規模1/2

^1/_2

1/2​

的子問題解的個數,即 4,24, 124

根據我們的分析,演算法的也就不難寫出來了,遞迴**如下

int

fun(

int n)

return cnt+1;

}

遞迴的方法雖然簡單直觀,但是提交沒過——超時了,遞迴深度太深導致爆棧了,這時候我們就需要思考能不能改進?能不能進一步優化?

還記得最初在學習遞迴的時候,乙個經典的案例就是斐波那契數列:f(n

)=f(

n−1)

+f(n

−2),

n≥

2f(n) = f(n-1) + f(n-2), n\geq2

f(n)=f

(n−1

)+f(

n−2)

,n≥2(2

)f(2)

f(2)

的值就被重複計算了三次,那麼我們能不能讓它只計算一次呢?

對於斐波那契數列的一種優化方法就是利用陣列暫存中間值,這樣就避免了重複計算

那麼什麼又是動態規劃?

遵循動態規劃演算法是將問題遞迴地分解成更簡單的重疊子問題,通過子問題的解決來解決原問題

動態規劃目前已廣泛應用於經濟學、計算機視覺、語音識別、人工智慧、計算機圖形學和生物資訊學

在斐波那契數列的例子中,多次計算的f(2

)f(2)

f(2)

的值,這樣就是乙個重疊的子問題,我們應避免重複計算帶來的時間開銷,於是引入了陣列——儲存每一次計算的值(這樣乙個過程稱為記憶, 對於提高遞迴演算法效率是很重要的技術)

我們有了思路,下面的關注點就在於尋找該問題的乙個遞推關係式

我們先列出來一部分:(其中f(n

)f(n)

f(n)

表示自然數n

nn所具有上述三種性質的個數)

f (1

)=

1f(1) = 1

f(1)=1

f (2

)=

2f(2) = 2

f(2)=2

f (3

)=

2f(3) = 2

f(3)=2

f (4

)=

4f(4) = 4

f(4)=4

f (5

)=

4f(5) = 4

f(5)=4

f (6

)=

6f(6) = 6

f(6)=6

f (7

)=

6f(7) = 6

f(7)=6

f (8

)=

10f(8) = 10

f(8)=10f(

9)=10

f(9) = 10

f(9)=1

0…我們可以看出:

綜上,我們可以得出遞推式:

f (1

)=

1f(1) = 1

f(1)=1

n

>

1n>1

n>1時

long

fun(

int n)

return a[n]

;}

學習演算法的道路漫長且艱鉅,唯有不斷打磨自己不斷思考,挖掘其背後的本質,才能取得進步

洛谷P1028 數的計算

我們要求找出具有下列性質數的個數 包含輸入的自然數n 先輸入乙個自然數n n 1000 然後對此自然數按照如下方法進行處理 1.不作任何處理 2.在它的左邊加上乙個自然數,但該自然數不能超過原數的一半 3.加上數後,繼續按此規則進行處理,直到不能再加自然數為止.輸入格式 乙個自然數n n 1000 ...

洛谷 P1028 數的計算

我們要求找出具有下列性質數的個數 包含輸入的自然數n 先輸入乙個自然數n n 1000 然後對此自然數按照如下方法進行處理 不作任何處理 在它的左邊加上乙個自然數,但該自然數不能超過原數的一半 加上數後,繼續按此規則進行處理,直到不能再加自然數為止.輸入格式 乙個自然數n n 1000 輸出格式 乙...

洛谷P1028 數的計算

我們要求找出具有下列性質數的個數 包含輸入的自然數 n 先輸入乙個自然數n n 1000 然後對此自然數按照如下方法進行處理 不作任何處理 在它的左邊加上乙個自然數,但該自然數不能超過原數的一半 加上數後,繼續按此規則進行處理,直到不能再加自然數為止.輸入格式 1 個自然數n n 1000 輸出格式...