• hdu 4472 count


    动态规划(递推)

    选拔赛的题目,也是2012国赛的题目。题意:给n个节点,构建一棵树,使到同一层的节点所拥有的子节点数相等,问能构建出多少个

    这句话,“使到同一层的节点所拥有的子节点数相等”,并没有把话说得很白,但是细想就可以发现,这句话是等同于说,这棵树是对称,而且非常对称,甚至可以想象到,以树根为轴,把树劈成两份,两边是对称的,取其中一边,再以树根劈开,两边还是对称的(这样强的对称性才满足题目说的那句话)

    所以基于这点,我们可以想到,除开树根外,下面的子树(可能一棵子树,或者两棵,多棵),一定要完全相同的,为什么?哪怕每棵子树是对称的,但是子树与子树之间不同,那么都挂在树根上的时候,是不能满足  “使到同一层的节点所拥有的子节点数相等” 的。

    因而问题来到这里就比较明显了,就是要找出一棵或多颗完全相同的,而且其本身也是强烈对称的子树,这不就是一个完全相同的子问题吗?因而递推就派上用场了

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

    总结:这题的英文本身也不好理解,能理解出中文的这句话“使到同一层的节点所拥有的子节点数相等” 是不容易的,能想到是由多颗完全相同的且其本身也完全对称的也不容易。当理解到这里,写代码已经是很容易的事情。

    #include <cstdio>
    #include <cstring>
    #define N 1010
    #define MOD 1000000007
    
    long long dp[N];
    int n;
    
    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()
    {
        DP();
        int ccase=0;
        while(scanf("%d",&n)!=EOF)
        {
            printf("Case %d: %lld\n",++ccase,dp[n]);
        }
        return 0;
    }
  • 相关阅读:
    java程序员从ThinkPad到Mac的使用习惯改变
    关于mybatis缓存配置详解
    log4j每天,每小时产生一日志文件
    $_SERVER常用
    curl抓取页面时遇到重定向的解决方法
    十三)CodeIgniter源码分析之Loader.php
    十二)CodeIgniter源码分析之Model.php
    十一)CodeIgniter源码分析之Controller.php
    十)CodeIgniter源码分析之Output.php
    九)CodeIgniter源码分析之Hook.php
  • 原文地址:https://www.cnblogs.com/scau20110726/p/2953104.html
Copyright © 2020-2023  润新知