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;
    }
    
    /*
    */
  • 相关阅读:
    NanoProfiler
    NanoProfiler
    Open Source Cassandra Gitbook for Developer
    Android Fragment使用(四) Toolbar使用及Fragment中的Toolbar处理
    Android Fragment使用(三) Activity, Fragment, WebView的状态保存和恢复
    Android Fragment使用(二) 嵌套Fragments (Nested Fragments) 的使用及常见错误
    Android Fragment使用(一) 基础篇 温故知新
    Set up Github Pages with Hexo, migrating from Jekyll
    EventBus源码解析 源码阅读记录
    Android M Permission 运行时权限 学习笔记
  • 原文地址:https://www.cnblogs.com/CJLHY/p/9126943.html
Copyright © 2011-2022 走看看