嘘~ 正在从服务器偷取页面 . . .

洛谷_


洛谷P2767 树的数量 题解

题目链接:P2767 树的数量

题意

求出包含 nn 个节点(无标号)的有根 mm 叉树的个数,对 1000710007 取模。

两个有根树相同,当且仅当其根节点相同,且从左到右每一棵子树也相同。特别地,两个有根树均为空树,视为两个有根树相同。

输入格式

输入两个整数 nnmm

输出格式

输出包含 nn 个节点(无标号)的有根 mm 叉树的个数,对 1000710007 取模后的值。数据范围

n,m127n,m127

这题可以 O(p+logmn)O(p+logmn) 做,需要用到生成函数&拉格朗日反演。不会,可以看这篇

这里讲 dp 的做法。

fi,jfi,j 表示 ii 个点,根节点有至多 jj 棵子树时的方案数。考虑转移

枚举点数 kk ,把这 kk 个点拆成一个新的子树算。容易发现不会算重。

fi,j=i1k=0fk,m×fik,j1fi,j=i1k=0fk,m×fik,j1

时间复杂度 O(n3)O(n3)

代码:

cpp
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
const int mod = 1e4+7;
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
void add(int &x,int y) { (x += y) >= mod ? x -= mod : 0; }
#define N ((int)(215))

int n,m,f[N][N];
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    
    cin >> n >> m;
    for(int i=0; i<=m; i++) f[0][i] = f[1][i] = 1;
    for(int i=2; i<=n; i++)
        for(int j=1; j<=m; j++)
            for(int k=0; k<i; k++)
                add(f[i][j], f[k][m] * f[i - k][j - 1] % mod);
    cout << f[n][m] << '\n';
    return 0;
}

参考文献

[1] https://www.luogu.com.cn/blog/87434/solution-p2767


文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
你认为这篇文章怎么样?
  • 0
  • 0
  • 0
  • 0
  • 0
  • 0
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v3.1.3
  目录