數的計算——遞歸與函數自調用算法

題目描述 Description
  咱們要求找出具備下列性質數的個數(包含輸入的天然數n):
  先輸入一個天然數n(n<=1000),而後對此天然數按照以下方法進行處理:
  1.不做任何處理;
  2.在它的左邊加上一個天然數,但該天然數不能超過原數的一半;
  3.加上數後,繼續按此規則進行處理,直到不能再加天然數爲止.
 輸入輸出格式 Input/output
輸入格式:
一個天然數n(n<=1000)
輸出格式:
一個整數,表示具備該性質數的個數。
 輸入輸出樣例 Sample input/output
樣例測試點#1
輸入樣例:
6
輸出樣例:
6
思路:
方法一:
用遞歸,f(n)=1+f(1)+f(2)+…+f(div/2),當n較大時會超時,時間應該爲指數級。
 
方法二:用記憶化搜索,其實是對方法一的改進。設h[i]表示天然數i知足題意三個條件的數的個數。若是用遞歸求解,會重複來求一些子問題。例如在求h[4]時,須要再求h[1]和h[2]的值。如今咱們用h數組記錄在記憶求解過程當中得出的全部子問題的解,當遇到重疊子問題時,直接使用前面記憶的結果。
 

方法三:算法

用遞推,用h(n)表示天然數n所能擴展的數據個數,則h(1)=1, h(2)=2, h(3)=2, h(4)=4, h(5)=4, h(6)=6, h(7)=6, h(8)=10, h(9)=10.分析以上數據,可得遞推公式:h(i)=1+h(1)+h(2)+…+h(i/2)。此算法的時間度爲O(n*n)。數組

設h[i]-i按照規則擴展出的天然數個數(1≤i≤n)。下表列出了h[i]值及其方案:
 
方法四:
w是對方法三的改進,咱們定義數組s,s(x)=h(1)+h(2)+…+h(x),h(x)=s(x)-s(x-1),此算法的時間複雜度可降到O(n)。
 
方法五:
w仍是用遞推,只要做仔細分析,其實咱們還能夠獲得如下的遞推公式: (1)當i爲奇數時,h(i)=h(i-1);
w     (2)當i爲偶數時,h(i)=h(i-1)+h(i/2).
 
代碼①以下(遞歸):
 1 #include<stdio.h>
 2 int ans;
 3 void dfs(int m)                           //統計m所擴展出的數據個數
 4 {
 5     int i;
 6     ans++;                                  //每出現一個原數,累加器加1;
 7     for (i = 1; i <= m/2; i++)         //左邊添加不超過原數一半的天然數,做爲新原數
 8     dfs(i); 
 9 }
10 int main()
11 {
12     int n;
13     scanf("%d",&n);
14     dfs(n);
15     printf("%d\n",ans);
16     return 0;
17 }

代碼②以下(非遞歸):測試

 1 #include <stdio.h>    
 2 int main()    
 3 {    
 4     int a[1001]={0};   
 5     int n,p;
 6     scanf("%d",&n);  
 7     a[1]=1;  
 8     a[2]=2;    
 9     for(p=3;p<=n;p++)
10     {
11         if(p%2==1) 
12         {
13             a[p]=a[p-1];   
14         }
15         else 
16         {
17             a[p]=a[p-1]+a[p/2];    
18         }                  
19     } 
20     printf("%d\n",a[n]);
21     return 0;    
22 }
相關文章
相關標籤/搜索