【BZOJ 1089】 [SCOI2003]严格n元树

1089: [SCOI2003]严格n元树

Time Limit: 1 Sec   Memory Limit: 162 MB
Submit: 872   Solved: 445
[ Submit][ Status]

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

dp+高精度。


f[i]表示深度<=i的n元树有几种。


f[0]=1

f[i]=f[i-1]^n+1 


这里的+1是加上深度为0的情况。


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
struct data
{
	int l,v[1005];
}f[20];
int n,d;
data operator *(data a,data b)
{
	data ans;
	for (int i=1;i<=1000;i++)
		ans.v[i]=0;
	ans.l=0;
	for (int i=1;i<=1000;i++)
		ans.v[i]=0;
	for (int i=1000;i>=1001-b.l;i--)
		for (int j=1000;j>=1001-a.l;j--)
			ans.v[i-(1000-j)]+=(b.v[i]*a.v[j]);
	int now=1001-(a.l+b.l-1);
	for (int i=1000;i>now;i--)
	{
		if (ans.v[i]<10) continue;
		ans.v[i-1]+=(ans.v[i]/10);
		ans.v[i]%=10;
	}
	ans.l=a.l+b.l-1;
	while (ans.v[now]>=10)
	{
		ans.l++;
		ans.v[now-1]+=(ans.v[now]/10);
		ans.v[now]%=10;
		now--;
	}
	return ans;
}
data operator ^(data a,int x)
{
	data ans;
	for (int i=1;i<=1000;i++)
		ans.v[i]=0;
	ans.l=1,ans.v[1000]=1;
	while (x)
	{
		if (x&1) ans=ans*a;
		a=a*a;
		x>>=1;
	}
	for (int i=1;i<=1000;i++)
		if (ans.v[i]) 
		{
			ans.l=1001-i;
			break;
		}
	return ans;
}
data operator +(data a,int x)
{
	a.v[1000]+=x;
	int now=1000;
	while (a.v[now]>=10)
	{
		a.v[now-1]+=(a.v[now]/10);
		a.v[now]%=10;
		now--;
	}
	for (int i=1;i<=1000;i++)
		if (a.v[i])
		{
			a.l=1001-i;
			break;
		}
	return a;
}
data operator -(data a,data b)
{
	for (int i=1000;i>=1001-a.l;i--)
	{
		a.v[i]-=b.v[i];
		if (a.v[i]<0)
			a.v[i]+=10,a.v[i-1]--;
	}
	while (!a.v[1001-a.l])
		a.l--;
	return a;
}
void Print(data a)
{
	for (int i=1001-a.l;i<=1000;i++)
		printf("%d",a.v[i]);
	cout<<endl;
}
int main()
{
    scanf("%d%d",&n,&d);
    f[0].l=1,f[0].v[1000]=1;
    for (int i=1;i<=d;i++)
        f[i]=(f[i-1]^n)+1;
    Print(f[d]-f[d-1]);
    return 0;
}



感悟:

1.WA多次,是对于数字长度的处理出错了


2.一开始对于这道题想的是f[i]表示深度为i的n元树个数,发现很难转移;设成<=i的就方便多了

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值