题解Luogu P1472 奶牛家谱 Cow Pedigrees

博客围绕Lg P1472奶牛家谱问题展开,该问题用二叉树表示奶牛关系,需计算满足特定条件的家谱树个数。最初设dp[i][j]为i个点刚好j层的方案数较复杂,后改为设其为i个点小于等于j层的方案数,最终答案为dp[n][k] - dp[n][k - 1],还给出转移方程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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][k1]是不是?
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,j1)+f(nl1,j1)

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值