尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

P14254 分割(树上计数问题) 题解

P14254 分割(树上计数问题) 题解
📅 发布时间:2026/6/19 22:57:07

P14254 树上组合计数(分割问题)题解

原题链接

一、题目分析

这部分是解题的核心,通过分析条件得出简化问题的关键结论。

  1. 计数问题先尝试找一下性质:

    • 注意到节点的选择只能越来越深

      \[d_i>=d_1 \]

    • 最关键性质:

      \[max L_i =d_i ,min R_i ==high_i \]

      \[L_i =d_i<=d_1,\therefore d_i=d_1 \]

  2. 所以所选点的深度相等

    • 定义“高度”hig[x]:结点x到其所在子树中叶子结点的最大深度(即子树内的最大深度)。
    • 核心约束:设选中结点均在深度为x的层,需满足“所有选中结点的高度最小值等于第一个结点的高度”(min Rᵢ = R₁,其中Rᵢ为结点i的高度)。

三、计数思路

基于上述性质,计数过程按“逐层处理”展开,每层内再按高度分组计算贡献。

1. 预处理步骤

  • 步骤1:计算深度与高度:通过DFS遍历树,记录每个结点的深度dep[x]和高度hig[x]。
  • 步骤2:分层与分组:
    • 按深度将结点分组,得到flr[i](存储深度为i的所有结点的高度)。
    • 对每层的flr[i]按高度排序,并进一步按相同高度分组,记录每组的结点数量(nt)和该组在层中的位置(bef,用于计算后续结点数)。

2. 每层贡献计算

对每个深度为i的层,若该层结点数<k+1,则直接跳过(无法满足选k个结点的基本条件);否则按以下公式计算该层的贡献:

(1)核心公式

对于高度相同的一组结点(数量为t,后续结点数为s,s=该层总结点数 - 该组位置bef):

  • 若满足t≥2(需至少2个结点,1个作为序列第一个元素,1个用于限制高度最小值)且t+s≥k+1(总可选结点数足够),则该组贡献为:

[ \text{贡献} = t \times \left( A(t+s-1, k-1) - A(s, k-1) \right) ]

  • 特殊情况:当s=k-1时,A(s, k-1)需强制设为0(此时后续结点数恰好为k-1,无法满足高度约束)。

(2)排列数定义

  • 排列数A(a, b)表示从a个元素中选b个元素进行有序排列的方案数。
  • 计算公式:若b<0或a<b,则A(a,b)=0;否则A(a,b)=fac[a] × inf[a-b] mod 998244353。
  • 其中fac为阶乘数组,inf为逆阶乘数组(通过费马小定理预处理,inf[n] = fac[n]^(M-2) mod M,M=998244353)。

四、代码实现

1.完整代码

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e6 + 5, M = 998244353;
struct Edge
{int to, next;
} e[N];
int head[N], idx = 0;
void addedge(int u, int v)
{e[idx].to = v;e[idx].next = head[u];head[u] = idx++;
}
int phi(int a, int b)
{int res = 1;while (b){if (b & (int)1)res = (res * a) % M;b >>= (int)1;a = (a * a) % M;}return res;
}
int n, k;
int dep[N], hig[N];
vector<int> flr[N];
int fac[N], inf[N];
void init()
{fac[1] = fac[0] = 1;for (int i = 1; i <= n; ++i)fac[i] = (fac[i - 1] * i) % M;inf[n] = phi(fac[n], M - 2);for (int i = n - 1; i >= 0; --i)inf[i] = (inf[i + 1] * (i + 1)) % M;
}
int maxdep = 0;
void dfs(int x)
{hig[x] = dep[x];maxdep = max(maxdep, dep[x]);for (int i = head[x]; ~i; i = e[i].next){int v = e[i].to;dep[v] = dep[x] + 1;dfs(v);hig[x] = max(hig[x], hig[v]);}
}
int A(int a, int b)
{if (b < 0 || a < b)return 0;return (fac[a] * inf[a - b]) % M;
}
struct Seg
{int nt = 0, bef = 0;
};
signed main()
{memset(head, -1, sizeof head);cin >> n >> k;for (int i = 2; i <= n; ++i){int t;cin >> t;addedge(t, i);}dep[1] = 1;dfs(1);init();for (int i = 1; i <= n; ++i)flr[dep[i]].push_back(hig[i]);int ans = 0;for (int i = 1; i <= maxdep; ++i){if (flr[i].size() < k + 1)continue;sort(flr[i].begin(), flr[i].end());vector<Seg> g;int cnt = 1;for (int j = 0; j < flr[i].size(); ++j){if (j < flr[i].size() && flr[i][j] == flr[i][j + 1])++cnt;elseg.push_back({cnt, j + 1}), cnt = 1;}for (Seg j : g){int t = j.nt, s = flr[i].size() - j.bef;if (t >= 2 && t + s >= k + 1){int t1 = A(t + s - 1, k - 1), t2 = A(s, k - 1);if (s == k - 1)t2 = 0;int tp = ((t1 - t2) % M + M) % M;ans = (ans + (t * tp) % M) % M;}}}cout << ans << endl;return 0;
}

2. 易错点提示

​ 排列数函数记得特判

3. 代码说明

  • 树的存储:使用邻接表(Edge结构体+head数组),适配1e6级别的结点规模。
  • 预处理优化:阶乘与逆阶乘通过费马小定理预处理,确保排列数计算O(1)。
  • 边界处理:
    • 排列数计算时判断a<b或b<0的情况,直接返回0。
    • 减法取模时加上M再取模,避免出现负数。

相关新闻

  • 完整教程:开源 C++ QT QML 开发(一)基本介绍
  • 102302104刘璇综合实践作业任务一:智能购物平台用户需求调研分析报告——基于195份问卷的用户痛点挖掘
  • 【C++实战(71)】解锁C++音视频编写:FFmpeg从入门到实战

最新新闻

  • 嵌入式MCU电气特性与FLASH操作深度解析:从数据手册到稳定设计
  • 2026 郑州八大装修公司综合实力排行榜 - GrowthUME
  • 爱回收到店估价和到手价差多少?iPhone 15 Pro实测报告 - 新闻快传
  • 2026沈阳非急救转运救护车TOP5盘点|辽中同城、浑河跨桥、棋盘山山地、院区转诊首选康跃转运 - 吉修匠
  • 2026长沙防水补漏权威指南:卫生间/屋面/外墙/地下室正规施工+透明报价+避坑全攻略 - 苏易修缮
  • 爱回收靠谱吗?一个测评博主的深度复盘 - 新闻快传

日新闻

  • 5分钟掌握Python进化算法:Geatpy高性能优化工具完全指南
  • Microchip 24AA044 EEPROM选型与应用全指南:从参数解析到实战编程
  • 华为的鸿蒙到底有多牛?为什么称作遥遥领先?

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号