NOIP2001 普及組複賽 第一題 數的計算

2022-05-13 04:33:28 字數 2090 閱讀 9420

題目描述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 2

intmain()

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 ...