实质上可以根据这道题的特性,把dp优化下,简直黑科技。处理出深度为d时,可能的最大节点数和最小节点数,这样转移就不会T了。。。还要注意这题输出贼坑,本来不少于九位的要输出前导0。。打表看一下分界点在38.。
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 3010
#define mod 1000000000
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
int n,dp[N][N],mx[N],mn[N],ans[N],d;
int main(){
// freopen("fin.in","r",stdin);
mx[1]=mn[1]=1;dp[0][0]=1;dp[1][1]=1;
for(d=2;d;d++){//mn[d],深度为d,满足要求的树的最小节点数
mn[d]=mn[d-1]+mn[d-2]+1;if(mn[d]>3000) break;
mx[d]=mx[d-1]+mx[d-1]+1;if(mx[d]>3000) mx[d]=3000;
for(int i=mn[d];i<=mx[d];++i)
for(int j=mn[d-1];j<=mx[d-1]&&j<i;++j){
dp[i][d]=((ll)dp[j][d-1]*dp[i-1-j][d-2]*2+dp[i][d])%mod;
dp[i][d]=(dp[i][d]+(ll)dp[j][d-1]*dp[i-1-j][d-1])%mod;
}
}
for(int i=1;i<=3000;++i)
for(int j=1;j<=d;++j) ans[i]=(ans[i]+dp[i][j])%mod;
while(1){
scanf("%d",&n);if(!n) break;
if(n>=38) printf("%09d\n",ans[n]);
else printf("%d\n",ans[n]);
}
return 0;
}