其他分享
首页 > 其他分享> > #21 CF830D

#21 CF830D

作者:互联网

Singer House

题目描述

点此看题

解法

同时路径计数问题,本题可以和 这题对比起来理解。

基本方法都是一样的,首先考虑计数顺序应该是自底向上的树形 \(dp\),但是计数顺序却和我们考虑的状态——有向路径产生了冲突,因为按照这样的计数顺序,有向路径从某个点来看,可能就是若干个分散的有向链。

为了解决这样的冲突,我们在 \(dp\) 的过程中就需要维护一个有向链分散,合并的过程。这个过程的计数可以通过记录有向链的数量来实现,设 \(f_{n,k}\) 表示深度为 \(n\) 的子树内有 \(k\) 条有向链的方案数,转移:

时间复杂度 \(O(n^3)\)

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int M = 405;
const int MOD = 1e9+7;
#define int long long
int read()
{
	int x=0,f=1;char c;
	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x*f;
}
int n,f[M][M];
int F(int n,int k)
{
	if(!k) return 1;
	if(n==1) return k==1;
	if(~f[n][k]) return f[n][k];
	int r=0;
	for(int i=0;i<=k;i++)
		r=(r+F(n-1,i)*F(n-1,k-i))%MOD;
	for(int i=0;i<k;i++)
		r=(r+F(n-1,i)*F(n-1,k-i-1))%MOD;
	for(int i=0;i<=k;i++)
		r=(r+2*k*F(n-1,i)%MOD*F(n-1,k-i))%MOD;
	for(int i=0;i<=k+1;i++)
		r=(r+k*(k+1)*F(n-1,i)%MOD*F(n-1,k-i+1))%MOD;
	return f[n][k]=r;
}
signed main()
{
	n=read();
	memset(f,-1,sizeof f);
	printf("%d\n",F(n,1));
}

标签:21,计数,cdot,leftarrow,int,include,节点,CF830D
来源: https://www.cnblogs.com/C202044zxy/p/16323248.html