我們要求找出具有下列性質數的個數(包含輸入的自然數n):
先輸入一個自然數n(n<=1000),然后對此自然數按照如下方法進行處理:
1. 不作任何處理;
2. 在它的左邊加上一個自然數,但該自然數不能超過原數的一半;
3. 加上數后,繼續按此規則進行處理,直到不能再加自然數為止.
一個數n
滿足條件的數的個數
6
6
6個數分別是:
6
16
26
126
36
136
分析:
1. 本題難度看似不大,但如果用遞歸來做的話耗時非常大,因為需要重復計算的數據量太大了。當然我們也可以采取一邊遞歸一邊儲存的方法,但計算量也還是不小,再進一步思考,實際上就是可以用如下的遞推法來做;
2. 例如要求f(6),經過分析,我們知道:f(6)=f(1)+f(2)+f(3)+1,也就是說,f(6)的答案數量是在它之前可以取的所有自然數的答案數量之和(6之前可以取1,2,3三個自然數),最后加1是指數字6本身也是一個答案;
3. 所以,我們可以知道f(n)=f(1)+f(2)+......f(trunc(n/2))+1;
4. 因此,要求f(n),我們只需用上述公式編一個遞推過程,把f(2)到f(n)全部求出即可,對於f(1000)也不超過1秒就能得到結果。
第二種算法:
1. 對於f(7)=f(6)是顯而易見的,也即f(2n+1)=f(2n)。那么,f(8)和f(7)之間有什么關系呢?
2. 分析可知:f(8)和f(7)的差別是,f(8)除了包含f(7)的所有情況外,還要多加上f(4),即:f(8)=f(7)+f(4)。因此可得:f(2n)=f(2n-1)+f(n)。只需據此編一個遞歸小過程或者用遞推方法即可。

1 #include <iostream> 2 using namespace std; 3 int main() 4 { 5 int i,n,ans,sum[1001]; 6 sum[0] = 0,sum [1] = 1; 7 cin>>n; 8 for(i = 2 ; i <= n ; i++) 9 { 10 ans = sum[i/2] + 1; 11 sum [i] = sum[i-1] + ans; 12 } 13 cout<<sum[n] - sum[n-1]<<endl; 14 return 0; 15 }