zoukankan      html  css  js  c++  java
  • HDU

    题目大意:给你一个树的直径k,要求每个点的度数不超过3, 问你有多少棵树满足条件。

    思路:好难啊。 主要思想就是将一棵无根二叉树树划分成有根二叉树。

    我们对k的分奇偶讨论:

    我们定义dp[ i ] 为深度为 i 的有根二叉树的种数, sum 为 dp 的前缀和。

    1.当k为偶数时,我们按直径的一般划分成2棵有根二叉树,两棵的深度都为 k / 2

    答案由两部分组成, dp[k / 2] (两棵有根二叉树一样的情况)  + C(dp[k / 2], 2) (两棵二叉树不一样的情况)

    2.当k为奇数时,我们可以划分成3棵有根二叉树, 其中两棵深度为 k / 2, 另一棵深度 <= k / 2

    我们分为两大类来讨论, 第三棵树的深度为 k / 2 和 不是 k / 2, 方法和上述的差不多。

    #include<bits/stdc++.h>
    #define LL long long
    #define fi first
    #define se second
    #define mk make_pair
    #define pii pair<int,int>
    #define piii pair<int, pair<int,int> >
    
    using namespace std;
    
    const int N = 1e5 + 10;
    const int M = 10000 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9 + 7;
    const double eps = 1e-6;
    
    LL dp[N], sum[N], ivn2, ivn6, k;
    LL fastPow(LL a, LL b) {
        LL ans = 1;
        while(b) {
            if(b & 1) ans = ans * a % mod;
            a = a * a % mod; b >>= 1;
        }
        return ans;
    }
    
    void add(LL &a, LL b) {
        a += b; if(a >= mod) a -= mod;
    }
    
    LL f2(LL a) {
        if(a < 2) return 0;
        return a * (a - 1) % mod * ivn2 % mod;
    }
    
    LL f3(LL a) {
        if(a < 3) return 0;
        return a * (a - 1) % mod * (a - 2) % mod * ivn6 % mod;
    }
    
    void init() {
        dp[0] = 1, sum[0] = 1;
        dp[1] = 1; sum[1] = 2;
        ivn2 = fastPow(2, mod - 2);
        ivn6 = fastPow(6, mod - 2);
    
        for(int i = 2; i < N; i++) {
            dp[i] = dp[i - 1] * sum[i - 2] % mod;
            add(dp[i] ,f2(dp[i - 1]));
            add(dp[i] ,dp[i - 1]);
    
            sum[i] = sum[i - 1];
            add(sum[i], dp[i]);
        }
    }
    
    
    int main() {
        init();
    
        while(scanf("%lld", &k) != EOF && k) {
            if(k == 1) {
                puts("1");
            } else if(k & 1) {
                int depth = k / 2;
                LL ans = 0;
                add(ans, dp[depth]);
                add(ans, f2(dp[depth]) * 2 % mod);
                add(ans, f3(dp[depth]));
    
                add(ans, dp[depth] * sum[depth - 1] % mod);
                add(ans, f2(dp[depth]) * sum[depth - 1] % mod);
                printf("%lld
    ", ans);
            } else {
                int depth = k / 2;
                LL ans = 0;
                add(ans, f2(dp[depth]));
                add(ans, dp[depth]);
                printf("%lld
    ", ans);
            }
        }
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    ruby安装方法
    移动端适配问题px->rem方法
    判断元素阶段类型
    domReady
    电梯导航
    判断浏览器的版本以及浏览器内核( 转发 )
    AWS
    Amazon S3
    Pipeline 模型
    RESTful API
  • 原文地址:https://www.cnblogs.com/CJLHY/p/9126943.html
Copyright © 2011-2022 走看看