HDU 5136 Yue Fei's Battle

题意:求直径上有K个点的不同构树个数(每个点度不超过3)。

二叉树满足每个点度不超过3,把直径从中间切开,两边就是二叉树了。

设dp[i] = 深度为i的不同构二叉树个数。

sum[i] = 深度不超过i的不同构二叉树个数。

那么二叉树的两个分支有3种情况:

一个分支深度为i-1, 另一个分支深度小于i-1,有dp[i-1] * sum[i-2]种方法;

两个分支深度都是i-1,两个分支不一样,有dp[i-1]*(dp[i-1]-1)/2种方法;

两个分支深度都是i-1,两个分支一样,有dp[i-1]种方法。

dp[i] = dp[i-1]*sum[i-2] + dp[i-1]*(dp[i-1]+1)/2

i = K / 2

当K为偶数时,两边的二叉树深度都是K/2,

考虑两边可能相同,可能不同,方案数为dp[i]*(dp[i]+1)/2;

当K为奇数时,中间的点连接3个分支,至少有2个分支深度为K/2。

当3个分支有一个分支深度小于K/2,方案数 dp[i]*(dp[i]+1)/2*sum[i-1]

当3个分支深度都是K/2:

当3个分支都相同,方案数 dp[i]

当3个分支2个相同,方案数为 dp[i] * (dp[i] - 1)

当3个分支互不相同,方案数 C(dp[i], 3)

所有情况加起来就行了。

Yue Fei‘s Battle

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 512000/512000 K (Java/Others)

Total Submission(s): 194    Accepted Submission(s): 59

Problem Description

Yue Fei is one of the most famous military general in Chinese history.He led Southern Song army in the wars against the Jin dynasty of northern China. Yue Fei achieved a lot of victory and hopefully could retake Kaifeng ,the former capital of Song occupied
by Jin. Fearing that retaking Kaifeng might cause the Jin to release former Emperor Song Qinzong, threatening his throne, Emperor Song Gaozong took some corrupted officers‘ advice, sending 12 urgent orders in the form of 12 gold plaques to Yue Fei, recalling
him back to the capital.

Then Yue Fei was put into prison and was killed under a charge of "maybe there is" treason. But later Yue Fei was posthumously pardoned and rehabilitated, and became a symbol of loyalty to the country. The four corrupted officers who set him up were Qin Hui,Qin
Hui‘s wife Lady Wang, Moqi Xie and Zhang Jun. People made kneeling iron statues of them and put the statues before Yue Fei‘s tomb (located by the West Lake, Hangzhou). For centuries, these statues have been cursed, spat and urinated upon by people. (Now please
don‘t do that if you go to Hangzhou and see the statues.)

One of the most important battle Yue Fei won is the battle in Zhuxian town. In Zhuxian town, Yue Fei wanted to deploy some barracks, and connected those barracks with roads. Yue Fei needed all the barracks to be connected, and in order to save money, he wanted
to build as less roads as possible. There couldn‘t be a barrack which is too important, or else it would be attacked by enemies. So Yue Fei required that NO barrack could connect with more than 3 roads. According to his battle theory, Yue Fei also required
that the length of the longest route among the barracks is exactly K. Note that the length of a route is defined as the number of barracks lied on it and there may be several longest routes with the same length K.

Yue Fei wanted to know, in how many different ways could he deploy the barracks and roads. All barracks could be considered as no different. Yue Fei could deploy as many barracks as he wanted.

For example, if K is 3,Yue Fei had 2 ways to deploy the barracks and roads as shown in figure1. If K is 4, the 3 kinds of layouts is shown in figure 2. (Thick dots stand for barracks, and segments stand for roads):

Please bring your computer and go back to Yue Fei‘s time to help him so that you may change the history.

Input

The input consists of no more than 25 test cases.

For each test, there is only one line containing a integer K(1<=K<=100,000) denoting the length of the longest route.

The input ends by K = 0.

Output

For each test case, print an integer denoting the number of different ways modulo 1000000007.

Sample Input

3
4
0

Sample Output

2
3

Source

2014ACM/ICPC亚洲区广州站-重现赛(感谢华工和北大)

#include <bits/stdc++.h>
using namespace std;
#define prt(k) cerr<<#k" = "<<k<<endl

typedef long long ll;
const ll mod = 1e9 + 7;
ll pmod(ll a, ll n)
{
    ll ret = 1;
    for (; n; n>>=1, a=a*a%mod)
        if (n&1)
        ret = ret * a % mod;
    return ret;
}
ll getinv(ll a)
{
    return pmod(a, mod - 2);
}
const int N = 100100;
ll dp[N + 5], sum[N + 5];
const ll inv2 = getinv(2);
ll sub(ll a, ll b)
{
    return (a - b + mod) % mod;
}
void init()
{
    dp[0] = 1;
    dp[1] = 1;
    sum[0] = 1;
    sum[1] = 2;
    for (int i=1;i<N;i++)
    {
        dp[i+1] = (dp[i] * sum[i-1] % mod);
        dp[i+1] = (dp[i+1] + (dp[i] + 1)%mod * dp[i] % mod * inv2 % mod) % mod;
        sum[i+1] = (sum[i] + dp[i+1]) % mod;
    }
}
ll C3(ll a)
{
    return ((a*sub(a,1)%mod) * sub(a,2) % mod) * getinv(6) % mod;
}
ll f(int K)
{
    int i = K / 2;
    ll ans = ((dp[i] * (dp[i] +  1)%mod) % mod * inv2 % mod ) % mod;
    ll tmp = ans;
    if (K%2==0) {
        return ans;
    }
    ans = (ans * sum[i-1]) % mod;
    ans = (ans + dp[i]) % mod;
    ans = (ans + (dp[i]-1+mod)%mod * dp[i] % mod) % mod;
    ans = (ans + C3(dp[i])) % mod;
    return ans;
}
int main()
{
    int K;
    init();
    while (cin>>K, K)
    {
        ll ans = f(K);
        cout<<ans<<endl;
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

HDU 5136 Yue Fei's Battle

时间: 2024-08-08 01:14:57

HDU 5136 Yue Fei's Battle的相关文章

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

Yue Fei&#39;s Battle(组合计数递推)

//求一个直径为 k 的树有多少种形态,每个点的度不超过 3 // 非常完美的分析,学到了,就是要细细推,并且写的时候要细心 还有除法取模需要用逆元 #include <iostream> #include <stdio.h> #include <string.h> #include <math.h> #include <stdlib.h> using namespace std; #define MOD 1000000007 #define L

[hdu5136]Yue Fei&#39;s Battle 2014 亚洲区域赛广州赛区J题(dp)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud 现场赛的时候由于有个地方有点小问题,没有成功AC,导致与金牌失之交臂. 由于今天下午有点事情,无法打重现,所以下午只是花了十分钟做了一道J题,抢了个FB,2333333333 Yue Fei's Battle Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 512000/512000 K (Java/Others)T

hdu 5136(dp计数)

题目链接 题意:直径为K的每个点的边数不超过3的相互不同构的树有多少种? 解法:把树的直径拉开,两边就是两棵二叉树了.子问题:一个深度为m的不同构的二叉树有多少种?dp[i]表示深度为i的个数.sum[i]表示dp的前缀和.转移方程就是:dp[i+1]=dp[i]*sum[i-1]+dp[i]+dp[i]*(dp[i]-1)/2; 然后回到原问题:如果K是偶数(想象中间有个虚拟的不动点),则两边是两棵深度为K/2的二叉树,答案为:dp[i]*(dp[i]-1)/2+dp[i] 如果K为奇数,则中

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为奇数时

2014ACM/ICPC亚洲区广州站题解

这一场各种计算几何,统统没有做. HDU 5129 Yong Zheng's Death HDU 5136 Yue Fei's Battle

2015.10.20 2014--- 广州

前两天练的了, 做了过的人最多的三道后 ---------- wtw发现第一题据说是西工大说的那个暴力出奇迹的题 第四题刚推出轨迹是个圆,,syh发现 ,,, 求的是圆和多边形的面积交--- 于是弃疗又开了另一场比赛---- Dogs' Candies The E-pang Palace 从30个点里面选择8个点组成两个矩形,使得它们的面积和最大 枚举每个矩形的左下,右上这两个点--- 虽然意识到了有大矩形包含小矩形的情况---- 这种包含的情况的时候,只算外面那个大矩形的面积----(sb地还

hdu 5093 Battle ships 最大二分匹配

Battle ships Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 589    Accepted Submission(s): 233 Problem Description Dear contestant, now you are an excellent navy commander, who is responsible

HDU 5542 The Battle of Chibi dp+树状数组

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5542 题意:给你n个数,求其中上升子序列长度为m的个数 可以考虑用dp[i][j]表示以a[i]结尾的长度为j的上升子序列有多少 裸的dp是o(n2m) 所以需要优化 我们可以发现dp的第3维是找比它小的数,那么就可以用树状数组来找 这样就可以降低复杂度 #include<iostream> #include<cstdio> #include<cstring> #include