HDU-4359-DP+C(n, m)大数求

原创 2012年08月11日 15:13:08

比赛的时候一直在敲这道题。一开题就盯住这个名字了。有人说他说是 treeDP 不一定真的是 treeDP。

总有时候别人会给你很诚恳的忠告。却只因自己陷得太深无法自拔。关键是自己不想出去。

跑题了。

读错题了。n,d. d 是说 深度恰好为 d , 我给理解为不超过 d 。 于是最后答案变成 ans(n,d) - ans(n, d-1) 就可以了。

C(n, m) 那个东西 , 由于里面有除法 , 不能直接 mod 。这里套了一个我完全不懂的模版 。

依然不能 AC 。后来输出到一个文件里, 发现里面有负数 。 发现有个三连乘 , 可能超 __int64 . 太贱了。

一道题,核心东西就那么一点,乱七八糟的一大堆。短木板原则么。

其实这道题我也不知道更像DP 还是组合数学 还是都不是 。

很多事 , 本来就不用分那么清楚。也分不清楚。


const int N = 370;
const __int64 mod = 1000000007;

__int64 dp[N][N], CC[N][N];


inline __int64 log2(__int64 n)
{
    __int64 a = 0;
    while(n)
    {
        a++;
        n>>=1;
    }
    return a;
}
__int64 Extend_euclid(__int64 a,__int64 b,__int64 &x,__int64 &y)
{
    __int64 d=0,t=0;
    if(b==0)
    {
        x=1;
        y=0;
        return a;
    }
    else
    {
        d=Extend_euclid(b,a%b,x,y);
        t=x;
        x=y;
        y=t-a/b*y;
    }
    return d;
}
__int64 Bignum_Div(__int64 a,__int64 b,__int64 mod)
{
    __int64 x=0,y=0;
    Extend_euclid(b,mod,x,y);//扩展gcd求出(2*n)*x-mod*k=1的x
    __int64 ans= a*x%mod;//ans/(2*n)%p = ((ans*x)/(2*n*x))%p=ans*x%mod; (p=1000000007,显然gcd(2*n,p)=1)
    while(ans<0)
        ans+=mod;
    return ans;
}
int64 ice(int64 x,int64 y,int64 mod)
{
	int64 temp=x,res=1;
	while(y)
	{
		if(y&1)
			res=(res*temp)%mod;
		temp=(temp*temp)%mod;
		y>>=1;
	}
	return res;
}
int64 cnm(int64 x,int64 y,int64 mod)
{
	int64 ans=1,a,b;
	for(int64 i=0;i<y;i++)
	{
		a=(x-i)%mod;
		b=(y-i)%mod;
		ans=ans*(a*ice(b,mod-2,mod)%mod)%mod;
	}
	return ans%mod;
}
__int64 lucas(__int64 x,__int64 y,__int64 mod)
{
	if(y==0)
		return 1;
	return (cnm(x%mod,y%mod,mod)*lucas(x/mod,y/mod,mod))%mod;
}

__int64 C(int n, int m)
{
    if(n==0 || m==0 || m>=n) return 1;
    if(CC[n][m]!=-1) return CC[n][m];
    __int64 ans = 1;
    int nn=n, mm=m;
    m = min( m, n-m );
    for(int i=1; i<=m; i++, n--)
    {
       ans=Bignum_Div( ans*(__int64)n%mod, (__int64)i, mod )%mod;
       //ans = ans*(__int64)n/(__int64)i%mod;
    }
    return CC[nn][mm] = ans;
}

__int64 dfs(int64 n, int64 d)
{
    d = min(n, d);
    if(dp[n][d]!=-1) return dp[n][d]; //记忆化
    int k = log2(n); //至少层数
    if(d<k) return dp[n][d] = 0; //你懂得
    if(n==1) return dp[n][d] = 1;
    if(n==0) return dp[n][d] = 1;
    int i, j;
    __int64 tmp = 0;
    for(i=0; i<n; i++)
    {
        __int64 tmp1 = dfs(n-i-1, d-1); //分给右孩子n-i-1个点
        if(tmp1==0) continue;
        __int64 tmp0 = dfs(i, d-1); //分给左孩子i个点
        if(tmp0==0) break;
        tmp =tmp+ C(n-2, i)*tmp0%mod*tmp1%mod; //分给左孩子的不是根节点,不是除根节点最大的点,所以有C(n-2, i)
        tmp %= mod;
    }
    return dp[n][d] = tmp*(__int64)n%mod; //根节点有n种
}

int main()
{
    int t, tt=0, n, d;
    memset(dp, -1, sizeof(dp));
    memset(CC, -1, sizeof(CC));
    __int64 ii, j;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&d);
        printf("Case #%d: %I64d\n", ++tt, (dfs(n, d)-dfs(n,d-1)+mod)%mod);
    }
    return 0;
}


【HDU5570 BestCoder Round 63 (div1)C】【期望DP 公式化简】balls n种求m种颜色,同颜色球数为x贡献为x方 求期望

balls Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Subm...

求C(m,n)的大数模板

#include #include #include #define MAXN 1000 int goc(int m,int n) { if(m

【HDU5542 2015 CCPC 南阳国赛C】【DP】The Battle of Chibi n个数中恰好长度为m的单升子序列数

#include #include #include using namespace std; const int Z=1e9+7; const int N=1005; int casenum,cas...

(hdu step 2.3.7)下沙的沙子有几粒?(简单DP:求有m个H,n和D,且任意索引上H的个数都要比D的个数多的方案数)

在写题解之前给自己打一下广告哈~。。抱歉了,希望大家多多支持我在CSDN的视频课程,地址如下:http://edu.csdn.net/course/detail/209题目:下沙的沙子有几粒?Time...

【HDU5565 BestCoder Round 62 (div1)C】【STL or 二分答案 or 计数排序】Clarke and baton n个人减肥m次求最后异或值

【HDU5565 BestCoder Round 62 (div1)C】【优先队列做法】Clarke and baton n个人减肥m次求最后异或值 #include #include #i...

hdu :4359(记忆化搜索DP)

左子树的和小于右子树的和 由于都是2的幂 所以只要且必须右子树上有剩下 数中最大的那个就可以了(当然左/右为空的特殊) 查询时注意 根节点的选取是任意的 所以有假如说有n个节点 那根节点就有n种选法...

!HDU 4359 左子树节点和小于右子树的树有多少种-dp

题意:n个节点,每个节点的权值为2^0,2^1....2^(n-1),求满足任何节点的左子树的节点和小于右子树的节点和的分配方案有多少种 分析: 由于等比数列的性质:1+2+....2^(k-1)...

hdu 4359 codeforces 9D 组合 二叉树 DP

感觉hdu 4359 跟 codeforces 9D就是差不多的题啊, 比赛时没能回想起来以前是怎么做的,赛后赶紧补习 codeforces 9D ,要求当前点左子树的所有点权都小于当前点的点权...

2012 Multi-University Training Contest 6-1010 hdu4359 Easy Tree DP?

这场比赛中的简单dp题。要求左子树所有值的和小于右子树所有值的和。 由于每个结点中的值都是2的几次方,那么就有这样一个很好的性质2^0+2^1+...+2^(n-1) 那么如果树中的左右子都有的...

hdu 4359 Easy Tree DP?

Best solutions for Problem 4359 Language : AllG++GCCC++CPascalJava Rank Author Exe. ...
  • zz_1215
  • zz_1215
  • 2012年08月10日 14:09
  • 684
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:HDU-4359-DP+C(n, m)大数求
举报原因:
原因补充:

(最多只允许输入30个字)