hdu 4472 Count DP 递推

题意:给你n 个点,构造一棵树,使得同一层结点的子节点个数相同,问能构建出多少个

重点思路:“同一层结点的子节点个数相同”,仔细想想这句话,就会发现,能满足这个关系的树,子树必定是对称的,也就是从根节点切开两部分,左子树依然是对称的,右子树也是对称的,不过这还不够,这个数的所有所以基于这点,我们可以想到,除开树根外,下面的子树(可能一棵子树,或者两棵,多棵),一定要完全相同的,为什么?哪怕每棵子树是对称的,但是子树与子树之间不同,那么都挂在树根上的时候,是不能满足 “使到同一层的节点所拥有的子节点数相等” 的。

有了这点,就可以及进行递推了,dp[i]=sum(dp[j])  (i-1)%j==0,,因为一个节点一定要用去做树根,所以剩下i-1个点,这i-1个节点把它分成几份,这几份完全相同,其本身强烈对称

代码:

#include <iostream>
#include <stdio.h>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <stack>
#define lson l,mid,num<<1
#define rson mid+1,r,num<<1|1
#define MOD 1000000007;
using namespace std;
long long dp[1010];
void DP()
{
    memset(dp,0,sizeof(dp));
    dp[1]=1;
    dp[2]=1;
    for(int i=3; i<=1000; i++)
        for(int j=1; j<=i-1; j++)
            if((i-1)%j == 0)
                dp[i] = (dp[i]+dp[j])%MOD;
}
int main()
{
    int n,g=1;
    DP();
    while(scanf("%d",&n)!=EOF)
    {
        printf("Case %d: %I64d\n",g++,dp[n]);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值