我們要求找出具有下列性質數的個數(包含輸入的正整數 n)。
先輸入乙個正整數n(n≤1000),然後對此正整數按照如下方法進行處理:
1.不作任何處理;
2.在它的左邊加上乙個正整數,但該正整數不能超過原數的一半;
3.加上數後,繼續按此規則進行處理,直到不能再加正整數為止。
輸入n, 輸出乙個整數(該整數我在**中用re[n]來表示)
表示具有該性質的數的個數;
(例如 6 左邊加乙個不大於 6 的一半的數 2 變為 26 , 2 的左邊還可以加不大於 2 的一半的數 1,變為 126)案例
輸入 6
輸出 6
案例中的 6 個數是 6,16,26,126,36,136
這道題可以直接遞迴, 也可以找到它的遞推式來做.
一 遞推解法
利用遞推求解首先就是要找到這道題的遞推式;
當我看懂題意後, 我首先羅列了從 1 開始的多個整數在進行操作後輸出的結果 re[i], 最終發現了這道題的遞推公式就是re[n] = 1 + re[1] + re[2] + re[3] + …+ re[n/2]; 並且初始條件re[1] = 1; 找到了遞推公式, 知道了初始條件我們就可以用這個遞推公式來做這道題了
以下是我利用該遞推式寫的**:
#
include
//遞推法求解;
using
namespace std;
int re[
10005
], n, ans;
intmain()
ans += re[i];}
cout << ans << endl;
return0;
}
二 遞迴解法
這道題還可以利用遞迴來計算, 但如果單純的用遞迴進行回溯,在這道題上就會卡時間(事實上我這樣做就是tle了), 所以又學習了一下, 知道了這裡用到了記憶化搜尋的思想;
就是你要用乙個陣列來記錄你之前已經遍歷過的情況, 再次遇到這種情況就不用再次呼叫函式再算一遍了, 直接把陣列中記錄這種情況的數輸出就行了, 這樣就避免了做過多的無用功, 提高了遞迴的效率;
那麼這道題的遞迴做法就可以用上這種思想了, 下面就是我寫的**了:
#
include
//遞迴法求解;
using
namespace std;
int re[
10005
], n, ans;
intsearch
(int x)
for(
int i =
1; i <= x /
2; i++
)return re[x]
= temp;
}int
main()
P1028 數的計算 (遞迴 遞推)
題目傳送門 思路 設a i 為n i時的方案數。可知當 i 不進行操作有一種方案,然後 i的左邊可以加1,2,i 2,然後又轉化為求解a 1 a 2 a i 2 的方案數。這顯然是乙個遞推過程,由於每個方案都是由字首和得到,所以我們可以用乙個陣列儲存字首和。遞推公式 a i a i 1 a i 2 ...
數的計算(dfs和遞推)
題目描述 我們要求找出具有下列性質數的個數 包含輸入的正整數 n 先輸入乙個正整數 n n 1000 然後對此正整數按照如下方法進行處理 不作任何處理 在它的左邊加上乙個正整數,但該正整數不能超過原數的一半 加上數後,繼續按此規則進行處理,直到不能再加正整數為止。輸入格式 1個正整數 n n 100...
遞推遞迴練習 F 計算組合數
description 計算組合數。c n,m 表示從n個數中選擇m個的組合數。計算公式如下 若 m 0,c n,m 1 否則,若 n 1,c n,m 1 否則,若m n,c n,m 1 否則 c n,m c n 1,m 1 c n 1,m input 第一行是正整數n,表示有n組要求的組合數。接下...