(數論)數的計算


題目描述  Description

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

先輸入一個自然數n(n<=1000),然后對此自然數按照如下方法進行處理:

1.          不作任何處理;

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

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

輸入描述  Input Description

一個數n

輸出描述  Output Description

滿足條件的數的個數

樣例輸入  Sample Input

6

樣例輸出  Sample Output

6

數據范圍及提示  Data Size & Hint

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 }
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM