zoukankan      html  css  js  c++  java
  • 【CF724F】Uniformly Branched Trees 动态规划

    【CF724F】Uniformly Branched Trees

    题意:询问n个点的每个非叶子点度数恰好等于d的不同构的无根树的数目。

    $nle 1000,dle 10$。

    题解:先考虑有根树的版本。我们用$DP(n,m,k)$表示n个点,其中根的度数为m,其余点度数为d,根的最大的儿子的子树不能超过k的方案数。转移时我们可以枚举有多少个子树大小为k的。假如有i个,则贡献为:$DP(n-ik,m-i,k-1) imes{{DP(k,d-1,k-1)+i-1} choose{i}}$,采用记忆化搜索是一个非常优秀的方法。

    如果是无根树呢?如果有一个点为重心,则我们令重心为根即可。如果有两个重心,我们枚举其中一个,用组合数算一算即可。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    int n,m;
    ll P;
    ll ine[1010];
    int f[1010][11][1010];
    ll DP(int n,int d,int k)
    {
    	k=min(k,n-1);
    	if(f[n][d][k]!=-1)	return f[n][d][k];
    	if((n==1&&d==m-1)||(n==1&&!d))	return 1;
    	if(n==1||!k)	return 0;
    	int j;
    	ll ret=DP(n,d,k-1),t=DP(k,m-1,k),tmp=1;
    	for(j=1;j*k<n&&j<=d;j++)
    	{
    		tmp=tmp*(t+j-1)%P*ine[j]%P;
    		ret=(ret+tmp*DP(n-k*j,d-j,k-1))%P;
    	}
    	return f[n][d][k]=ret;
    }
    int main()
    {
    	scanf("%d%d%lld",&n,&m,&P);
    	if(n==1||n==2)
    	{
    		puts("1");
    		return 0;
    	}
    	if((n-2)%(m-1)!=0)
    	{
    		puts("0");
    		return 0;
    	}
    	int i;
    	ine[0]=ine[1]=1;
    	for(i=2;i<=n;i++)	ine[i]=P-(P/i)*ine[P%i]%P;
    	memset(f,-1,sizeof(f));
    	ll ans=DP(n,m,(n-1)/2);
    	if(!(n&1))
    	{
    		ll t=DP(n/2,m-1,n/2-1);
    		ans=(ans+t*(t+1)/2)%P;
    	}
    	printf("%lld",ans);
    	return 0;
    }
  • 相关阅读:
    在 Java 中遍历 HashMap 的5种最佳方式
    Java 8 Stream.reduce() 使用示例
    Redis 为什么这么快?
    java8 常用代码
    为什么我们越娱乐反而会越无聊?
    Arrays.sort() VS Arrays.parallelSort()
    Java中枚举类型Enum的一种使用方式
    An illegal reflective access operation has occurred
    多线程中常见锁概述
    Java中创建多线程的三种方式
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/8503868.html
Copyright © 2011-2022 走看看