bzoj1089-[SCOI2003]严格n元树

Description

  如果一棵树的所有非叶节点都恰好有n个儿子,那么我们称它为严格n元树。如果该树中最底层的节点深度为d
(根的深度为0),那么我们称它为一棵深度为d的严格n元树。例如,深度为2的严格2元树有三个,如下图:

  给出n, d,编程数出深度为d的n元树数目。

Input

  仅包含两个整数n, d( 0   <   n   <   =   32,   0  < =   d  < = 16)

Output

  仅包含一个数,即深度为d的n元树的数目。

Sample Input

【样例输入1】
2 2

【样例输入2】
2 3

【样例输入3】
3 5

Sample Output

【样例输出1】
3

【样例输出2】
21

【样例输出2】

58871587162270592645034001



用f(d)表示树的深度<=d的个数(f(0)=1);

对于一个n元树(我们假设要求的d>=3);

那么根节点的n个儿子的构造方法有f(d-1)^n种;

至于为什么是f(d)=f(d-1)^n+1;

是因为还要加上f(0)=1;

答案就是f(d)-f(d-1)

代码:

#include<cstdio>
#include<memory.h>
#include<cstring>

#define maxnum 100
#define cas 1000000000

int a[maxnum],b[maxnum],t[maxnum],al=1,bl;

inline void mul()
{
	memset(t,0,(al+bl+1)*4);
	for(int i=0;i<al;i++)
		for(int j=0;j<bl;j++)
		{
			long long f=(long long)a[i]*b[j];
			t[i+j]+=f%cas;
			if(t[i+j]>=cas)t[i+j]-=cas,t[i+j+1]++;
			t[i+j+1]+=f/cas;
			if(t[i+j+1]>=cas)t[i+j+1]-=cas,t[i+j+2]++;
		}
	if(t[al+bl-1])al=al+bl;else al=al+bl-1;
	memcpy(a,t,al*4);
}

inline void print(int *a){printf("%d",a[al-1]);for(int i=al-2;i>=0;i--)printf("%09d",a[i]);printf("\n");}

int main()
{
	int n,d;
	scanf("%d%d",&n,&d);
	a[0]=1;
	while(d--)
	{
		memcpy(b,a,al*4);
		bl=al;
		for(int i=1;i<n;i++)mul();
		a[0]++;
		for(int i=0;a[i]>=cas;i++)a[i]-=cas,a[i+1]++;
		if(a[al])al++;
	}
	for(int i=0;i<bl;i++)a[i]-=b[i];
	for(int i=0;i<al;i++)if(a[i]<0)a[i]+=cas,a[i+1]--;
	if(!a[al-1])al--;
	print(a);
	printf("\n");
	return 0;
}

解法由WSQ,YFZ提供

link to my blog

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值