HDU - 5136 2014icpc南京现场赛J 计数dp

题目大意:给你一个树的直径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\n", ans);
        } else {
            int depth = k / 2;
            LL ans = 0;
            add(ans, f2(dp[depth]));
            add(ans, dp[depth]);
            printf("%lld\n", ans);
        }
    }
    return 0;
}

/*
*/

原文地址:https://www.cnblogs.com/CJLHY/p/9126943.html

时间: 2024-11-09 00:00:18

HDU - 5136 2014icpc南京现场赛J 计数dp的相关文章

hdu 5136 Yue Fei&#39;s Battle(计数DP)

Yue Fei's Battle Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 512000/512000 K (Java/Others) Total Submission(s): 151    Accepted Submission(s): 48 Problem Description Yue Fei is one of the most famous military general in Chinese history.He

HDU 4815 2013长春现场赛C题

C - Little Tiger vs. Deep Monkey Time Limit:1000MS     Memory Limit:65535KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 4815 Description A crowd of little animals is visiting a mysterious laboratory ? The Deep Lab of SYSU. "Are y

hdu 4810 思维题+二进制位规律+异或规律 213南京现场赛题

http://acm.hdu.edu.cn/showproblem.php?pid=4810 以前做过一些涉及异或的题,化为二进制形式,然后统计0,1个数是一种很常见的处理方法,但是在做这个题的时候居然没尝试,脑残啊...... 一开始看5s时限,感觉稍微暴力一点应该可以,于是YY的O(n^3)算法但是没去实现,明显超时啊,大致就是通过C(n,1)的组合可以在O(n^2)内处理出C(n,2)的组合,在通过C(n,2)处理出C(n,3)的组合....但是C(n,2)已经是n^2个数了,所以算法是O

hdu 4802 水题 算GPA 南京现场赛

http://acm.hdu.edu.cn/showproblem.php?pid=4802 今天心情不太好,因为跟一个学姐谈,她似乎保研有点被动,而我的条件其实不如她应该...祝她好运.刷道水题调整下心情 写的有点慢,因为没读题,直接看图,然后N P没考虑以及0/0的情况也没考虑,虽然1A,但是自己代码速度还可以,但是综合起来做题速度还是.... //#pragma comment(linker, "/STACK:102400000,102400000") #include <

HDU 4462 Scaring the Birds (2012年杭州赛区现场赛J题)

1.题目描述:点击打开链接 2.解题思路:本题是一道简单模拟题.不过重点还是对于题目细节的理解.容易犯2个理解错误:(1)误以为是每个稻草人有不同的scaring range,实际上scaring range是由不同的vacant intersection决定的,跟稻草人毫无关系.(2)误以为所有点都需要被覆盖,实际上题目要求的是只要所有corn被保护就行,插稻草人的地方本来就是空地,有没有被保护无所谓的.由于题目给的范围非常小,完全可以通过枚举集合来确定哪些位置需要稻草人,如果这些稻草人成功的

2013长沙赛区现场赛 J - Josephina and RPG

J - Josephina and RPG Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 4800 Description A role-playing game (RPG and sometimes roleplaying game) is a game in which players assume the roles of cha

hdu 5078 2014鞍山现场赛 水题

http://acm.hdu.edu.cn/showproblem.php?pid=5078 现场最水的一道题 连排序都不用,因为说了ti<ti+1 //#pragma comment(linker, "/STACK:102400000,102400000") #include <cstdio> #include <cstring> #include <algorithm> #include <string> #include &l

hdu 5073 2014鞍山现场赛题 物理题

http://acm.hdu.edu.cn/showproblem.php?pid=5073 推公式即可,质心公式segma(xi*wi)/segma(wi) 最终剩下的一定是连续n-k个星 然后枚举左边需要移除几个星即可 计算I的时候展开来算 比较坑的地方在于,星星的位置如果是int型,一定记得Double计算的时候 *1.0或者直接将位置数组声明为double  否则WA到死... //#pragma comment(linker, "/STACK:102400000,102400000&q

hdu 4070 福州赛区网络赛J 贪心 ***

优先发路程最长的 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #define MOD 1000000007 10 const int INF=0x3f3