Lg P1472 奶牛家谱 Cow Pedigrees
奶牛家谱
(nocows.cpp/in/out)
题目描述
农民约翰准备购买一群新奶牛。 在这个新的奶牛群中, 每一个母亲奶牛都生两个小奶牛。这些奶牛间的关系可以用二叉树来表示。这些二叉树总共有N个节点(3 <= N < 200)。这些二叉树有如下性质:
每一个节点的度是0或2。度是这个节点的孩子的数目。
树的高度等于K(1 < K < 100)。高度是从根到最远的那个叶子所需要经过的结点数; 叶子是指没有孩子的节点。
有多少不同的家谱结构? 如果一个家谱的树结构不同于另一个的, 那么这两个家谱就是不同的。输出可能的家谱树的个数除以9901的余数。
输入输出格式
输入格式:
两个空格分开的整数, N和K。
输出格式:
一个整数,表示可能的家谱树的个数除以9901的余数。
输入输出样例
输入样例:
5 3
输出样例:
2
思路及分析
设 d p [ i ] [ j ] dp[i][j] dp[i][j]表示i个点刚好j层的方案数,然后弄个4层循环,还有组合数什么乱七八糟的,不仅思维难度高,编程难度高,时空复杂度都高!
既然设刚好j层那么麻烦,我们不妨设dp[i][j]表示i个点小于等于j层的方案数,那么最终我们所需的答案就是
d
p
[
n
]
[
k
]
−
d
p
[
n
]
[
k
−
1
]
dp[n][k]-dp[n][k-1]
dp[n][k]−dp[n][k−1]是不是?
via
所以说转移方程:
f
(
i
,
j
)
=
Σ
f
(
l
,
j
−
1
)
+
f
(
n
−
l
−
1
,
j
−
1
)
f(i,j)=\Sigma f(l,j-1)+f(n-l-1,j-1)
f(i,j)=Σf(l,j−1)+f(n−l−1,j−1)
T2::CODE
#include <bits/stdc++.h>
#define mod 9901
using namespace std;
const int maxn=210;
template <typename t>void read(t &x)
{
x=0;int 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();}
x=x*f;
}
int n,m,dp[maxn][maxn];
void init()
{
freopen("Lg P","r",stdin);
}
void readdata()
{
read(n),read(m);
}
void work()
{
for(int i=1;i<=m;i++)dp[1][i]=1;
for(int k=1;k<=m;k++)
{
for(int i=3;i<=n;i=i+2)
{
for(int j=1;j<i;j=j+2)
{
dp[i][k]+=dp[j][k-1]*dp[i-j-1][k-1];
dp[i][k]=dp[i][k]%mod;
}
}
}
printf("%d",(dp[n][m]-dp[n][m-1]+mod)%mod);
}
int main()
{
// init();
readdata();
work();
return 0;
}