題目描述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 #include2**②如下(非遞迴):intans;
3void dfs(int m) //
統計m所擴充套件出的資料個數410
intmain()
11
1 #include 2intmain()
3;
5int
n,p;
6 scanf("
%d",&n);
7 a[1]=1
; 8 a[2]=2
;
9for(p=3;p<=n;p++)
1015
else
16
19}
20 printf("
%d\n
",a[n]);
21return
0;
22 }
2023年NOIP普及組複賽題解
題目涉及演算法 這道題目可以用動態規劃進行求解。我們令 f i 表示自然數為 i 能夠生成的數的個數,則 f i 1 sum f j 實現 如下 include using namespace std const int maxn 1010 int n,f maxn int main cout f ...
NOIP 2001普及組 數的劃分
題目描述 我們要求找出具有下列性質數的個數 包含輸入的自然數n 先輸入乙個自然數n n 1000 然後對此自然數按照如下方法進行處理 1.不作任何處理 2.在它的左邊加上乙個自然數,但該自然數不能超過原數的一半 4.加上數後,繼續按此規則進行處理,直到不能再加自然數為止。題目分析 看到這道題,最容易...
NOIP2001提高組複賽B 數的劃分
略方法為減而治之,把n劃分成k份的答案就相當於每次把n分成a,b兩個數,再把a分成k 1份,然後把每次a分成k 1份的答案相加即可。注意點是每輪分出來的b要不大於上一輪分出來的b。1 include 2 using namespace std 34 define rep i,n for int i ...