ACdream 1412 2-3 Trees

本文介绍了一种计算特定数量叶子节点的2-3树总数的算法,并通过动态规划和组合数计算来解决该问题。输入为叶子节点数量及模数,输出为不同2-3树的数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

      2-3 tree is an elegant data structure invented by John Hopcroft. It is designed to implement the same functionality as the binary search tree. 2-3 tree is an ordered rooted tree with the following properties:

  • the root and each internal vertex have either 2 or 3 children;
  • the distance from the root to any leaf of the tree is the same.

      The only exception is the tree that contains exactly one vertex — in this case the root of the tree is the only vertex, and it is simultaneously a leaf, i.e. has no children. The main idea of the described properties is that the tree with l leaves has the height O(log l).
      Given the number of leaves l there can be several valid 2-3 trees that have l leaves. For example, the picture below shows the two possible 2-3 trees with exactly 6 leaves.


      Given l find the number of different 2-3 trees that have l leaves. Since this number can be quite large, output it modulo r.

Input

      Input file contains two integer numbers: l and r (1 ≤ l ≤ 5 000, 1 ≤ r ≤ 10 9).

Output

      Output one number — the number of different 2-3 trees with exactly l leaves modulo r.

Sample Input

6 1000000000
7 1000000000

Sample Output

2

3

dp递推+暴力求组合数

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const long long maxn = 2505;
long long f[maxn],c[maxn][maxn],n,m;

int main()
{
	while (cin >> n >> m)
	{
		memset(f, 0, sizeof(f));
		for (int i=1;i+i<=n;i++)
		{
			c[i][0]=c[i][i]=1;
			for (int j=1;j<i;j++) 
				c[i][j]=(c[i-1][j-1]+c[i-1][j])%m;
		}
		f[1]=1;
		for (long long i=2;i<=n;i++)
		{
			f[i]=0;
			for (long long j=0;j+j+j<=i;j++)
			if ((i-3*j)%2==0)
			{
				(f[i]+=f[j+(i-3*j)/2]*c[j+(i-3*j)/2][j])%m;
				(f[i]+=m)%=m;
			}
		}
		cout<<f[n]%m<<endl;
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值