BZOJ 3057圣主的考验题解
2024-09-06 11:58:46
老师居然考这么毒瘤的题目!!!!!
很容易想到dp,f[i][j]表示有i个节点,左子树的最深深度为j的方案数
枚举左子树有多少节点然后转移,复杂度为n^3
T飞~
我们考虑到有深度为h的树的节点有多少,可以发现深度为h的节点有着一定的范围
设minn为深度为h的树最少有多少节点,maxh为深度为h的数最多有多少节点
很显然minn[h]=minn[h-1]+minn[h-2]+1,maxh[h]=2^h-1
我们每一次转移时依然枚举左子树节点个数i,再次枚举深度是只需要枚举所有minn[h]<=i,切maxh[h]>=h的深度h
这样复杂度就变成了n^2*h,h为maxh[h]>3000的第一个h大约为20
但是它神奇的T掉了,我也不知道为什么......
# include<cstdio>
# include<cstring>
# include<cstdlib>
# include<algorithm>
using namespace std;
typedef long long LL;
const int mn = ;
const int mod = ;
int maxh[],minh[],L[mn + ],R[mn + ];
LL dp[mn + ][],ans[mn + ]; int main ()
{
dp[][]=dp[][]=, ans[]=;
minh[]=,minh[]=;
for(int i=;i<=;i++)
minh[i]=minh[i-]+minh[i-]+;
for(int i=;minh[i]<=mn && i<= ;i++)
for(int j=minh[i];j<min(minh[i+],mn+);j++)
R[j]=i;
maxh[]=;
for(int i=;i<=;i++)
maxh[i]=maxh[i-]*+;
L[]=;
for(int i=;maxh[i-]<=mn && i<=;i++)
for(int j=maxh[i-]+;j<=min(maxh[i],mn);j++)
L[j]=i;
for(int i=;i<=mn;i++)
{
for(int l=;l<i;l++)
{
int r=i--l;
for (int h=max(,L[i]-);h<=min(,R[i]-);h++)
{
if(h)
dp[i][h+]+=dp[l][h]*dp[r][h-];
(dp[i][h+]+=dp[l][h]*dp[r][h])%=mod;
dp[i][h+]+=dp[l][h]*dp[r][h+];
}
}
for(int h=;h<=min(,i);h++)
ans[i]+=dp[i][h];
ans[i] %= mod;
}
int n;
while(scanf("%d",&n),n)
printf(n>= ? "%09lld\n" : "%lld\n",ans[n]);
return ;
}
最新文章
- C# Excel导入、导出【源码下载】
- 显示或隐藏div
- 【HDU 1150】Machine Schedule(二分图匹配)
- 【转】Apache的Order Allow,Deny 详解
- Educational Codeforces Round 15 [111110]
- json_encode和json_decode
- wifi-sdio接口
- ST10 Bootstrap Loader
- 转载 .htaccess文件RewriteRule语法规则
- Unity3D资源存放笔记
- poj1664 放苹果(递归)
- MapReduce并行编程模型和框架
- 洛谷P2822 组合数问题(题解)
- EvansClassification
- NPM,bower的安装目录
- python可变对象和不可变对象的解释
- TI 开发板安装USB转串口驱动
- 【转】分布式一致性算法:Raft 算法(Raft 论文翻译)
- bzoj1566: [NOI2009]管道取珠 DP
- in文件