解题报告-洛谷SCP2025T2 P14254 分割(divide)

news/2025/10/19 17:47:41/文章来源:https://www.cnblogs.com/Starpop/p/19151157

洛谷SCP2025T2 P14254 分割(divide)

题目描述

你是洛咕咕王国的土地测绘官。洛咕咕王国并购了一块新的领土,这块新的领土正等待被分配。

这块领土可被认为是一棵有 \(n\) 个结点、结点编号为 \(1\)\(n\) 的树,根为编号 \(1\)。为了便于表述,我们把每个结点 \(i\) 在原树中的深度记作 \(d_i\),并规定根的深度为 \(1\)

你的王国有若干位诸侯希望购买土地,因此现在要从这棵树中选出 \(k\)两两不同的结点,并把它们的编号排成一个有序序列 \(b=(b_1,b_2,\dots,b_k)\)。这个序列必须满足两个条件:

第一,每个被选的结点都不是根,并且它们的深度是非降的,也就是对所有 \(1\le i<k\)\(1 < d_{b_i} \le d_{b_{i+1}}\)

第二,按照序列里每一个结点 \(b_i\)\(i=1,2,\cdots,k\)),把它们各自与父亲的连边断开。断开这些 \(k\) 条边后,原树会被分成 \(k+1\) 棵互不相交的连通子树。我们把这 \(k+1\) 棵子树依次编号。其中,第 \(1\) 棵到第 \(k\) 棵对应于根为 \(b_1,\dots,b_k\) 的那 \(k\) 棵子树,而第 \(k+1\) 棵子树则是剩下的、包含原来的树根 \(1\) 的那一棵(它的根仍记为 \(1\))。对于第 \(i\) 棵子树,把该子树中所有结点在原树中的深度值去重后组成一个集合,记为 \(S_i\)。要求这次分割满足等式:

\[S_1 = \bigcap_{i=2}^{k+1} S_i \]

换言之,第 \(1\) 棵子树中出现的所有深度恰好是“出现在所有其他子树中的深度”的交集。

我们把任意两个序列 \(b\) 视为不同的方案当且仅当它们作为序列不同(即结点相同但顺序不同视为不同方案)。你的任务是计算满足上述条件的序列 \(b\) 的个数,对 \(998244353\) 取模后输出结果。

输入格式

第一行包含两个正整数 \(n,k\),分别表示树的结点个数和需要选出的结点个数。

第二行包含 \(n-1\) 个正整数,第 \(i\) 个正整数表示结点 \((i+1)\) 的父结点的编号 \(p_i\)。根结点 \(1\) 没有父结点。

输出格式

输出一行一个整数,表示满足题目条件的序列 \(b\) 的个数,结果对 \(998244353\) 取模。

输入输出样例 #1

输入 #1

11 2
1 2 3 1 1 5 6 8 1 10

输出 #1

4

输入输出样例 #2

输入 #2

13 3
1 2 3 1 1 5 6 8 1 10 11 7

输出 #2

72

输入输出样例 #3

输入 #3

7 3
1 1 1 1 2 3

输出 #3

12

说明/提示

【样例解释 #1】

如图,合法的序列 \(b\) 一共有 \(4\) 个,分别是:

  • \(b_1 = 5, b_2 = 10\)
  • \(b_1 = 10, b_2 = 5\)
  • \(b_1 = 7, b_2 = 11\)
  • \(b_1 = 11, b_2 = 7\)

\(b_1 = 5, b_2 = 10\) 为例,\(d_5 = 2\)\(d_{10} = 2\),有 \(d_5 \le d_{10}\)。当我们切断结点 \(5\)\(10\) 与其父结点 \(1\) 的连边后,原树被分割成三棵子树。第一棵子树以 \(b_1=5\) 为根,包含结点 \(\{5, 7\}\);第二棵子树以 \(b_2=10\) 为根,包含结点 \(\{10, 11\}\);第三棵子树则是包含原树根 \(1\) 的剩余部分。

对于第一棵子树,其结点在原树中的深度为 \(\{2, 3\}\),因此 \(S_1 = \{2, 3\}\)。对于第二棵子树,其结点深度同样为 \(\{2, 3\}\),所以 \(S_2 = \{2, 3\}\)。对于包含根结点的第三棵子树,去重后的深度集合为 \(S_3 = \{1, 2, 3, 4\}\)。计算交集可得 \(S_2 \cap S_3 = \{2, 3\}\),与 \(S_1\) 相等。因此 \(b_1 = 5, b_2 = 10\) 是一个符合条件的序列。

【样例解释 #2】

一个符合条件的序列 \(b\)\(b_1 = 4, b_2 = 9, b_3 = 12\)

【样例 #4】

见选手目录下的 divide/divide4.individe/divide4.ans

这个样例满足测试点 \(8\) 的条件限制。

【样例 #5】

见选手目录下的 divide/divide5.individe/divide5.ans

这个样例满足测试点 \(13\) 的条件限制。

【样例 #6】

见选手目录下的 divide/divide6.individe/divide6.ans

这个样例满足测试点 \(21\sim 25\) 的条件限制。


【数据范围】

本题共 \(25\) 个测试点,每个测试点占 \(4\) 分,共 \(100\) 分。

测试点编号 \(n\le\) 特殊性质
\(1\sim 2\) \(12\)
\(3\sim 5\) \(10^2\)
\(6\sim 7\) \(2\times 10^3\)
\(8\) ^ A
\(9\sim 10\) \(2\times 10^5\) ^
\(11\sim 12\) \(10^6\) ^
\(13\) \(2\times 10^5\) B
\(14\sim 15\) \(10^6\) ^
\(16\sim 20\) \(2\times 10^5\)
\(21\sim 25\) \(10^6\)

特殊性质 A:\(k=2\)
特殊性质 B:树为一棵满 \(t\) 叉树,其中 \(t \in [3,n)\cap \Z\)

对于 \(100\%\) 的数据,保证 \(2\le k< n\le10^6\)\(1 \leq p_i < i\)。树保证连通。


解题报告

数学还是不行,比赛时推导的式子太复杂并且太难调了,最终只得了 \(40\text{pts}\)

有一个很明显的性质,就是所选的节点必须在原树中的同一深度

为什么?首先所选的节点的深度必须不降,同时可以发现,如果节点 \(b_i(i >1)\) 的深度 \(dep_{b_i}\)\(b_1\) 的深度 \(dep_{b_1}\) 大,那么 \(S_i\) 相比于 \(S_1\) 肯定不包含深度 \([dep_{b_1},dep_{b_i}+1]\),也就不可能是合法情况。所以 所选的节点必须在原树中的同一深度。

那么我们就先把原树上的节点按深度分类,并求出每个子树的最长链的长度(即子树的根节点的高度)。

显然,为了满足条件,所选的节点 \(b_1\) 肯定是高度最小的。

因此,对于每一种深度,我们取出每个节点的高度并从小到大排序后,统计每一种高度的数量并用组合数学计算。这是为了保证 \(b_1\) 高度最小。

设一共有 \(tot\) 种高度,当前处理到第 \(h\) 种高度,数量为 \(cnt\),设 \(sum_{[l,r]}\) 表示高度在区间 \([l,r]\) 的节点个数。

计算方案数时有以下几点:

  • 显然,只有 \(sum[h,tot] \geq K+1\) 时才能有合法方案,\(+1\) 是保证原树的剩下部分的高度同样大于等于 \(b_1\)
  • 从当前高度所属的节点种选一个选为 \(b_1\),共有 \(cnt \times A_{sum_{[h,tot]}}^{k-1}\) 种总方案(包括合法和不合法的)。
  • 注意,如果 \(sum_{[h+1,tot]} \geq k\),我们就需要扣除不合法的方案数 \(A_{sum_{[h+1,tot]}}^{k-1}\),这是由于必须要选一个与 \(b_1\) 同高度的 \(b_2\) 来限制之后的并集。

比赛的时候脑卡了没有想到可以容斥,就硬分类讨论,成功把程序调爆了(可恶啊,我的 \(100\) 分和珍贵的时间!!!)。

时间复杂度 \(O(n \log n)\),修改后的正确代码如下:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int INF=0x3f3f3f3f;
const int mod=998244353;
const int N=3001100;#define ckmax(x,y) ( x=max(x,y) )
#define ckmin(x,y) ( x=min(x,y) )inline int read()
{int f=1,x=0; char ch=getchar();while(!isdigit(ch)) { if(ch=='-') f=-1; ch=getchar(); }while(isdigit(ch))  { x=x*10+ch-'0';    ch=getchar(); }return f*x;
}vector<int> e[N];
vector<int> pos[N];
int n,m,K,p[N];
int NUM[N],tot;void dfs(int u,int dep)
{pos[dep].push_back(u);ckmax(m,p[u]=dep);for(int i=0;i<e[u].size();i++){int v=e[u][i]; dfs(v,dep+1);ckmax(p[u],p[v]);}
}inline int FastPow(int x,int k)
{int tot=1;x%=mod;while(k){if(k&1) tot=(tot*x)%mod;x=(x*x)%mod;k>>=1;}return tot;
}int fact[N],infact[N];
inline void GetFact()
{fact[0]=1;for(int i=1;i<N;i++)fact[i]=fact[i-1]*i%mod;infact[N-1]=FastPow(fact[N-1],mod-2);for(int i=N-2;i>=0;i--)infact[i]=infact[i+1]*(i+1)%mod;
}inline int C(int n,int m)
{ return fact[n]*infact[m]%mod*infact[n-m]%mod; }inline int A(int n,int m)
{ return fact[n]*infact[n-m]%mod; }signed main()
{// freopen("divide.in","r",stdin);// freopen("divide.out","w",stdout);// 洛谷还是搞一个要用 freopen 的测评方式吧。n=read();K=read(); GetFact();for(int i=2;i<=n;i++)e[read()].push_back(i);dfs(1,1);int ans=0;for(int i=2;i<=m;i++){tot=0;for(int j=0;j<pos[i].size();j++)NUM[++tot]=p[pos[i][j]];sort(NUM,NUM+tot+1);int l=1,r=0;while(l<=tot){while(r<tot && NUM[r+1]==NUM[l]) r++;int cnt=r-l+1,sum=tot-l+1,suc=tot-r;if(sum>=K+1){ans=(ans+cnt*A(sum-1,K-1))%mod;if(suc>=K) ans=(ans-cnt*A(suc,K-1)%mod+mod)%mod;}l=r+1;}}printf("%lld\n",ans%mod);return 0;
}

这里附上 \(40\text{pts}\) 的神秘赛事代码,以表警示:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int INF=0x3f3f3f3f;
const int mod=998244353;
const int N=3001100;#define ckmax(x,y) ( x=max(x,y) )
#define ckmin(x,y) ( x=min(x,y) )inline int read()
{int f=1,x=0; char ch=getchar();while(!isdigit(ch)) { if(ch=='-') f=-1; ch=getchar(); }while(isdigit(ch))  { x=x*10+ch-'0';    ch=getchar(); }return f*x;
}vector<int> e[N];
vector<int> pos[N];
int n,m,K,p[N];
int NUM[N],tot;
int cnt[N],top;void dfs(int u,int dep)
{pos[dep].push_back(u);ckmax(m,p[u]=dep);for(int i=0;i<e[u].size();i++){int v=e[u][i]; dfs(v,dep+1);ckmax(p[u],p[v]);}
}inline int FastPow(int x,int k)
{int tot=1;x%=mod;while(k){if(k&1) tot=(tot*x)%mod;x=(x*x)%mod;k>>=1;}return tot;
}int fact[N],infact[N];
inline void GetFact()
{fact[0]=1;for(int i=1;i<N;i++)fact[i]=fact[i-1]*i%mod;infact[N-1]=FastPow(fact[N-1],mod-2);for(int i=N-2;i>=0;i--)infact[i]=infact[i+1]*(i+1)%mod;
}inline int C(int n,int m)
{ return fact[n]*infact[m]%mod*infact[n-m]%mod; }inline int A(int n,int m)
{ return fact[n]*infact[n-m]%mod; }inline int calc1(int sum)
{int ans=0;for(int j=1;j<=top;j++){if(sum<K+1) break;for(int k=2;k<=min(K-1,cnt[j]) && top>1;k++)ans=(ans+k*C(cnt[j],k)%mod*C(sum-cnt[j],K-k)%mod*A(K-1,K-1)%mod)%mod;if(cnt[j]>=K) ans=(ans+A(cnt[j],K))%mod;sum-=cnt[j];}return ans;
}inline int calc2(int sum)
{int ans=0;for(int j=1;j<=top;j++){sum-=cnt[j];if(sum>K || cnt[j]<=K-sum) continue;ans=(ans+C(cnt[j],K-sum)%mod*(K-sum)%mod*A(K-1,K-1)%mod)%mod;}return ans;
}signed main()
{n=read();K=read(); GetFact();for(int i=2;i<=n;i++)e[read()].push_back(i);dfs(1,1);int ans=0;for(int i=2;i<=m;i++){top=0,tot=0;int sum=0;for(int j=0;j<pos[i].size();j++)NUM[++tot]=p[pos[i][j]];sort(NUM,NUM+tot+1);for(int j=1;j<=tot;j++){if(NUM[j]!=NUM[j-1])sum+=cnt[top++];cnt[top]++;}sum+=cnt[top];if(sum>K){if(top>1){ans=(ans+calc1(sum))%mod;ans=(ans+calc2(sum))%mod;}elseans=(ans+A(sum,K))%mod;}for(int j=1;j<=top;j++) cnt[j]=0;}printf("%lld\n",ans%mod);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/940478.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

fluent-bit采集k8s(kubernetes-docker)容器日志

下面是一份补全后的文档,基于你上传的 YAML 内容,整理为 Markdown 说明文档,方便团队使用和复用。文中还特别标注了注意事项 ⚠️,帮助避免常见配置错误。📦 Kubernetes 命名空间与权限配置文档 本文档示例演示了…

别看我只是一只羊

梦回童年喜羊羊 美羊羊 懒羊羊 沸羊羊 慢羊羊 软绵绵 红太狼 灰太狼 别看我只是一只羊 绿草因为我变得更香 天空因为我变得更蓝 白云因为我变得柔软 别看我只是一只羊 羊儿的聪明难以想象 天再高心情一样奔放 每天都追…

2025年智能照明系统/模块厂家推荐排行榜,工厂/改建/车间/高亮/高光效/泛光/免维护/投光/大功率智能照明系统/模块公司精选!

2025年智能照明系统/模块厂家推荐排行榜,工厂/改建/车间/高亮/高光效/泛光/免维护/投光/大功率智能照明系统/模块公司精选!随着科技的不断进步和智能化趋势的加速发展,智能照明系统和模块在工业、商业以及民用领域得…

Pr 入门

Pr 入门项目浏览 双击素材进入源编辑器窗口。 源编辑器 选择片段范围:i 入点 o 出点。option + i 取消入点,option + o 取消出点,option + x 取消全部。 , 时间线中从当前位置插入当前所选片段 . 时间线中从当前位置…

10.19 —— (VP)2022icpc西安

最暴露真实水平的一把。只做出来 \(4\) 道纯签到题,但其实这把的前 \(6\) 题都是签到题级别,切签到的速度也不快,罚时还上天。 \(F,J\) 没啥好说的。 \(C\) 题能感觉到一定是先克隆,再出题。\(O(\log n)\) 枚举克隆…

2025年储罐源头厂家推荐排行榜,钢衬塑/钢塑复合/化工/防腐/PE/盐酸/硫酸/聚丙烯/不锈钢/次氯酸钠储罐公司精选!

2025年储罐源头厂家推荐排行榜:钢衬塑/钢塑复合/化工/防腐/PE/盐酸/硫酸/聚丙烯/不锈钢/次氯酸钠储罐公司精选!随着工业和化工行业的快速发展,储罐作为关键的储存设备,在各个领域中发挥着重要作用。无论是用于储存…

2025.10.19——1绿1蓝

普及+/提高 P5020 [NOIP 2018 提高组] 货币系统 训练题,不难想到DP 提高/省选- P5021 [NOIP 2018 提高组] 赛道修建 训练题,二分+贪心我想到了,但是这个贪心的策略出了点问题。 以前没做过这样的贪心,看完题解之后…

2025年TYPE-C母座厂家推荐排行榜,防水/板上/沉板/立插/立贴/侧插/立式/插座/接口/插头/5A大电流/高速/TID认证公司精选

2025年TYPE-C母座厂家推荐排行榜:防水/板上/沉板/立插/立贴/侧插/立式/插座/接口/插头/5A大电流/高速/TID认证公司精选随着科技的不断进步,TYPE-C接口因其高效、高速和多功能的特点,逐渐成为电子设备连接的主流选择…

26-wsl-nginx-chinese-encoding-fix

Windows 11 WSL 中 Nginx 中文乱码问题解决方案 问题描述 在 Windows 11 WSL 环境中安装了 Nginx,虽然可以正常访问,但是返回的中文内容在 Windows 浏览器中显示为乱码。 问题原因Nginx 默认配置中没有明确设置字符编…

Redis 有序集合解析 - 指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

win10-减少广告的三个操作

今天有学到一招,可以减少电脑弹框广告。 第一招:右键【显示设置】点击【通知和操作】将【通知】进行关闭第二招:右侧的【专注助手】同样也关闭第三招:点击上方【主页】找到【隐私】然后进行关闭:打完收工!

变量名越怪,JVM 越快?

在软件工程的共识里,变量命名越清晰越好——意图明确、语义完整、见名知意,这能降低沟通成本、减少误解、提升可维护性。几乎所有风格指南都把“有意义的命名”视为第一原则。 但今天读到的一篇文章《Java Performs …

科技领域导师制度与因果分析方法解析

本文探讨了科技行业中数据科学与经济学的交叉应用,重点介绍了因果分析方法如双重差分法和倾向得分匹配,并分享了导师制度在科技人才培养中的重要性及实践经验。导师的承诺与职业轨迹 Nanneh Chehras 是一位资深经济学…

小迪安全v2023学习笔记(九十六讲)—— 云原生篇Docker安全系统内核版本漏洞CDK自动利用容器逃逸 - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

完整教程:使用Celery处理Python Web应用中的异步任务

完整教程:使用Celery处理Python Web应用中的异步任务pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas&qu…

Visual Studio Code 初步配置指南(Windows端)

0x00 简介 本文将介绍如何从0开始初步配置Visual Studio Code(Windows端)(用于编写C语言程序)。 本文以Windows11 24H2系统演示。 如果你还没有决定是否使用VSCode,可以前往0x06章节预览VSCode是如何编写运行程序…

2025年UV光源厂家推荐排行榜,UV面光源,UV LED点光源,UV LED面光源,UV LED固化机公司精选

2025年UV光源厂家推荐排行榜:UV面光源,UV LED点光源,UV LED面光源,UV LED固化机公司精选随着科技的不断进步,UV光源在各个行业中的应用越来越广泛。从印刷、涂装到电子制造,UV光源以其高效、环保的特点成为不可或…

深度学习基础从0到0.1

线性回归 一元线性回归 线性回归,公式为Y=Wx+b,这里简单一点,假设偏置b=0,我们设置损失函数为loss=(y-yi),y是真实值,yi是预测值,代入可得loss=(y-W*x),带入x的值和y的值即可得到最终的loss函数,而后求其导数…

比赛与好题记录(2025 9-10)

随便写写。 P14115 [IAMOI R4] 木桶效应 有一个木桶,由 \(n\) 块竖直木板组成,第 \(i\) 块木板高度为 \(a_i\)。 我们可以在这些木板上加装额外的木板:有 \(m\) 块 高度为 1 的木板; 有 \(k\) 块 高度为 \(h\) 的木…