hdu 2292 Minimum Heap

来源:互联网 发布:淘宝统计数据 编辑:程序博客网 时间:2024/06/05 22:32

动态规划的题目,只需要用根节点的左孩子中的结点总数能组成的组合总数*右孩子中的结点总数能组成的组合总数然后再乘从这棵子树的总结点数选择出一个孩子结点数的组合数就可以了。这样本题就好做了,可以写一个递归函数解决。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2292

#include <iostream>using namespace std;const int maxn=1005;__int64 n,m;__int64 cnt[maxn];int c[maxn][maxn];int son(int n)//求左孩子中的节点个数{    int t = 1;    while (t <= n) t=t<<1|1;    t = (t - 1) / 2;    t = (t - 1) / 2;    int sum = n - 1 - t;    if (sum > 2 * t + 1){        sum = 2 * t + 1;    }    return sum;}void calc_c() {//递推求组合数    for (int i = 0; i < maxn; i++)     {        c[i][0] = c[i][i] = 1;        for (int j = 1; j < i; j++)         {            c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % m;        }    }}__int64 slove(int n)//求n个结点的树共有多少种组合{    if(cnt[n])        return cnt[n];    if(n==0||n==1)        return 1;    int left=son(n);    int right=(n-1)-left;    return cnt[n]=( (slove(left)*slove(right) )%m )*(__int64)c[n-1][left]%m;}int main(){    int T;    scanf("%d",&T);    while(T--)    {        memset(cnt,0,sizeof(cnt));        scanf("%I64d%I64d",&n,&m);        calc_c();        __int64 ans=slove(n);        printf("%I64d\n",ans);    }    return 0;}


原创粉丝点击