【題目描述】
我們要求找出具有下列性質數的個數(包括輸入的自然數n)。先輸入一個自然數n(n≤1000),然后對此自然數按照如下方法進行處理:
不作任何處理;
在它的左邊加上一個自然數,但該自然數不能超過原數的一半;
加上數后,繼續按此規則進行處理,直到不能再加自然數為止。
【輸入】
自然數n(n≤1000)。
【輸出】
滿足條件的數。
【輸入樣例】
6
【輸出樣例】
6
看完題目以及樣例輸入與輸出,本人便把這6種情況列舉了出來:
- 6
- 16
- 26
- 126
- 36
- 136
那么就特別簡單,設一個函數Dfs,一直遞歸“1~參數/2”,每次遞歸的同時增加符合條件的數的數量即可:
【方法一】遞歸f(n)=1+f(1)+f(2)+···+f(n/2)
#include<cstdio> #include<iostream> #include<cmath> #include<cstring> #include<iomanip> #include<string> using namespace std; int num=0; int dfs(int n){ num++; for(int i=1;i<=n/2;i++){ dfs(i); } } int main(){ int n; cin>>n; dfs(n); cout<<num; }
提交后,情況如下:
測試點 1: 答案正確 460KB 3MS
測試點 2: 答案正確 464KB 3MS
測試點 3: 答案正確 456KB 2MS
測試點 4: 答案正確 464KB 2MS
測試點 5: 答案正確 476KB 4MS
測試點 6: 答案正確 456KB 2MS
測試點 7: 答案正確 464KB 2MS
測試點 8: 答案正確 452KB 2MS
測試點 9: 答案正確 468KB 310MS
測試點10: 運行超時 456KB 994MS
反正第9、10個點不知道已經跑到哪去了,耗時十分離譜
那么,往下看
【方法二】記憶化搜索
#include<iostream> #include<cstdio> #include<iomanip> #include<cstring> using namespace std; const int SB=-1438; int num[2000]; void Dfs(int n){ if(num[n]!=SB)return;//前面有結果了就不用再算 num[n]=1; for(int i=1;i<=n/2;i++){ Dfs(i); num[n]+=num[i];//統計數量,so easy } } int main(){ int n; cin>>n; for(int i=1;i<=n;i++)num[i]=SB; Dfs(n); cout<<num[n];
return 0; }