zoukankan      html  css  js  c++  java
  • HDU 2292

    http://acm.hdu.edu.cn/showproblem.php?pid=2292

    题意:1-n个节点,题目给出了完全二叉树的定义(这个定义似乎有歧义,此题以题目描述为准),且要保持最小堆性质(根节点小于左右子树内的任意元素),问有多少种不同组合

    解法:dp,dp[n]表示n个元素的合法排列数量。一共n个节点,左子树有a个节点,则右子树有n-1-a个节点,dp[n]=C(n-1,a)*dp[a]*dp[n-1-a],其中a可以轻易算出。

    公式解释:除去根节点,在剩下的n-1个元素中取a个,这a个元素的合法排列有dp[a]种,剩下n-1-a个节点的合法排列有dp[n-1-a]种。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std ;
    typedef __int64 ll ;
    ll c[1005][1005],n,m,dp[1005] ;
    ll cal(int s)
    {
        ll temp=s-1 ;
        ll cnt=2 ;
        ll ans=0 ;
        while(temp-cnt>0)
        {
            ans+=cnt/2 ;
            temp-=cnt ;
            cnt*=2 ;
        }
        if(temp>=cnt/2)ans+=cnt/2 ;
        else ans+=temp ;
        return ans ;
    }
    int main()
    {
        int t ;
        scanf("%d",&t) ;
        while(t--)
        {
            scanf("%I64d%I64d",&n,&m) ;
            memset(c,0,sizeof(c)) ;
            for(int i=1 ;i<1001 ;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 ;
            }
            memset(dp,0,sizeof(dp)) ;
            dp[0]=dp[1]=1 ;
            for(int i=2 ;i<=n ;i++)
            {
                ll a=cal(i) ;
                ll b=i-1-a ;
                dp[i]=c[i-1][a]*dp[a]%m*dp[b]%m ;
            }
            printf("%I64d
    ",dp[n]%m) ;
        }
        return 0 ;
    }
    View Code
  • 相关阅读:
    2018.8.5 复习笔记
    C#抽象类与接口的区别【转】
    double转整数问题
    C++学习笔记
    BCG使用
    C++设计模式之工厂方法模式
    静态成员函数
    CTreeCtrl 控件使用总结
    WinAPI: ShellExecute
    C++ STL map使用
  • 原文地址:https://www.cnblogs.com/xiaohongmao/p/3713441.html
Copyright © 2011-2022 走看看