【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的就方便多了

时间: 2024-10-06 06:44:44

【BZOJ 1089】 [SCOI2003]严格n元树的相关文章

bzoj 1089 [SCOI2003]严格n元树(DP+高精度)

1089: [SCOI2003]严格n元树 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1250  Solved: 621[Submit][Status][Discuss] Description 如果一棵树的所有非叶节点都恰好有n个儿子,那么我们称它为严格n元树.如果该树中最底层的节点深度为d(根的深度为0),那么我们称它为一棵深度为d的严格n元树.例如,深度为2的严格2元树有三个,如下图: 给出n, d,编程数出深度为d的n元树数目. Inp

BZOJ 1089: [SCOI2003]严格n元树

Decription 询问深度为 \(d\) 的 \(n\) 元树个数, \(n\) 元树所有节点的孩子都有 \(n\) 个. Sol 递推+高精度. \(f[i]\) 表示深度为 \(i\) 的 \(n\) 元树个数,我这里深度是从 \([1,k+1]\) 的... 转移就是从上方添加一个节点,子节点任选然后再减去不合法的方案. \(f[i]=(\sum ^{i-1} _{j=1} f[j])^n-(\sum ^{i-2} _{j=1} f[j])^n\) Code #include<cstd

BZOJ 1089 SCOI2003 严格n元树 动态规划+高精度

题目大意:定义一棵深度为d的严格n元树为根的深度为0,最深的节点深度为d,且每一个非叶节点都有恰好n个子节点的树 给定n和d,求深度为d的严格n元树一共同拥有多少种 此题的递推部分并不难 首先我们设深度为i的严格n元树一共同拥有f[i]种 令S[i]为f[i]的前缀和 我们不难发现一棵深度为i下面的严格n元树由两部分组成:一个根节点,n棵子树.当中每棵子树的深度不超过i-1 每棵子树有S[i-1]种 一共n棵子树 于是S[i]=S[i-1]^n 嗯?是不是少了点东西?没错,另一种情况,这棵严格n

【BZOJ】1089: [SCOI2003]严格n元树(递推+高精度/fft)

http://www.lydsy.com/JudgeOnline/problem.php?id=1089 想了好久的递推式,,,然后放弃了QAQ 神思路!orz 首先我们设$f[i]$表示深度最大为i的n元树的数目,注意,是最大深度为i! 那么易得递推式 f[i]=f[i-1]^n+1 前面表示子树的情况乘积,后面表示树为1层!因为1层是合法的!即没有子女! 然后答案就是 f[d]-f[d-1] !!!为什么要剪掉呢?因为看我们的转移,并不是深度为i,而是深度最大为i,那么为什么要这样减呢?理由

【noi 2.6_9280】&amp;【bzoj 1089】严格n元树(DP+重载运算符)

题意:定义一棵树的所有非叶节点都恰好有n个儿子为严格n元树.问深度为d的严格n元树数目. 解法:f[i]表示深度为<=i的严格n元树数目.f[i]-f[i-1]表示深度为i的严格n元树数目.f[i]=f[i-1]^n+1.d层的严格n元树可分解为1个根节点和n棵d-1层的严格n元树.利用乘法原理,再加上子树为空的一种情况. P.S.同样要注意递推的思想! 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring&

1089: [SCOI2003]严格n元树

好久没更新了..于是节操掉尽python水过本来就水的题.. 1 n,d=map(int, raw_input().split()) 2 if d==0: 3 print 1 4 else: 5 f=[1] 6 for i in range(0, d+1): 7 f.append(f[i]**n+1) 8 print f[d]-f[d-1]

[BZOJ1089][SCOI2003]严格n元树(递推+高精度)

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1089 分析: 第一感觉可以用一个通式求出来,但是考虑一下很麻烦,不好搞的.很容易发现最底层必有一个是满高度的,其他的任意. 所以直接的递推也不好想. (以下所述都是n元树) 于是可以令f[d]为深度<=d的树的个数,那么深度为d的就是f[d]-f[d-1] 对于深度<=d的又该怎么处理呢? 考虑第一层的n个点(根为0层),每个点都要底下连子树,深度为0~i-1,方案数即f[d-1]

BZOJ1089 [SCOI2003]严格n元树

又是一道奇怪的DP(?)题一个非常好的想法是:令f[i]表示深度小于等于i的n元树的总个数,于是f[i] = f[i - 1] ^ n + 1 (这是因为加了一层以后新的根的n个儿子可以随便选,再加上没有儿子的情况)但是还要写高精...还好一边A了,手感不错~ 1 /************************************************************** 2 Problem: 1089 3 User: rausen 4 Language: Pascal 5 R

P4295 [SCOI2003]严格N元树 DP

思路:DP 提交:\(5\)次 错因:\(2\)次高精写错(我太菜了),\(2次\)写错特判 题解: 设\(f[i]\)表示深度\(\leq i\)的严格\(n\)元树的数目,有 \[f[i]=pow(f[i-1],n)+1\] 即一个点,对于每一个孩子深度都可以是\(1\)到\(i-1\)的严格\(n\)元树,或是仅仅一个点(作为根). 所以最后的答案是\(f[i]-f[i-1]\) 需要高精. #include<cstdio> #include<iostream> #inclu