洛谷 P5853 - [USACO19DEC]Tree Depth P(生成函数+背包)
神仙题。
首先考虑一个点的深度是什么,注意到对于笛卡尔树而言直接从序列的角度计算一个点的深度是不容易的,因为这样会牵扯到序列中多个元素,需要 fixed 的东西太多,计算起来太复杂了。因此考虑从树本身的角度计算一个点的深度。注意到对于一棵树上所有点 \(u\) 而言都有 \(dep_u=\sum\limits_{v}[\text{LCA}(u,v)=v]\),因此我们求解一个点 \(x\) 的答案时,可以枚举所有 \(u,v\) 并计算 \(v\) 对 \(u\) 的贡献,即,有多少个排列满足逆序对个数为 \(k\),且笛卡尔树上 \(v\) 为 \(u\) 的祖先。并且我们还可以注意到,对于一个序列而言,其笛卡尔树上某两点存在祖先关系是存在充要条件转化的,具体来说,\(\text{LCA}(u,v)=v\) 当且仅当 \(a_v\) 为 \(a[\min(u,v)…\max(u,v)]\) 的最小值,因此我们只需求解以下问题:
有多少个排列 \(p\),满足其逆序对个数为 \(k\),且 \(a_v=\min\limits_{i=\min(u,v)}^{\max(u,v)}a_i\)
这个问题看似难以下手,因为外面就已经枚举了两维 \(u,v\) 了,里面这东西也无法直接组合数求解,需要用 DP 之类的东西,一弄最低就是 \(n^3\),直接爆炸,不过细想其实不用复杂度那么高。我们首先考虑如果没有第二个条件怎么求,我们设 \(dp_{i,j}\) 表示有多少个长度为 \(i\) 的排列有 \(j\) 个逆序对,考虑怎么转移,不难发现,对于长度为 \(i+1\) 的排列,我们总能找到唯一的 \(a_{i+1}\),满足 \(a_{i+1}\) 与前面 \(i\) 个数产生的逆序对数为 \(x(x\in[0,i])\),也就是说 \(dp_{i+1,j}=\sum\limits_{x=0}^idp_{i,j-x}\),前缀和优化一下即可,这个在 CF1542E2 Abnormal Permutation Pairs (hard version) 中就已经见过了。对于此题亦是如此,与经典问题不同的一点是,直接按照 \(1,2,3,\cdots,n\) 的位置填数会爆炸,因此考虑换个顺序,如果 \(u<v\) 那么我们就按照 \(u,u+1,u+2,\cdots,v,u-1,u-2,\cdots,1,v+1,v+2,\cdots,n\) 的顺序填数,否则我们按照 \(u,u-1,u-2,\cdots,v,u+1,u+2,\cdots,n,v-1,v-2,\cdots,1\) 的顺序填。不难发现按照这样的顺序填数之后,其他位置上的填法都和前面一样,即第 \(i\) 个填的数可以为排列逆序对数产生 \([0,i-1]\) 中任意一个数的贡献,唯独 \(v\) 只有一种填法。而两种情况的差别的,前一种情况 \(v\) 会对排列逆序对数产生 \(|u-v|\) 的贡献,而后一种不会,因此如果写成生成函数的形式,就是前一种情况的方案数为 \([x^k]·x^{|u-v|}\prod\limits_{i=0}^{|u-v|-1}(\sum\limits_{j=0}^ix^j)·\prod\limits_{i=|u-v|+1}^{n-1}(\sum\limits_{j=0}^ix^j)\),后一种情况的方案数为 \(x^{|u-v|}\prod\limits_{i=0}^{|u-v|-1}(\sum\limits_{j=0}^ix^j)·\prod\limits_{i=|u-v|+1}^{n-1}(\sum\limits_{j=0}^ix^j)\),注意到对于一对 \(u,v\) 而言,上面两个式子的值只与 \(|u-v|\) 有关,因此可以对所有 \(|u-v|\) 预处理一波答案,复杂度 \(\mathcal O(n^4)\)。如果你观察能力再强一些,你还能发现这式子可以写成背包的形式,你对前后缀各做一遍背包就可以 \(n^3\) 求解了。
const int MAXN=300;
const int MAXK=44850;
int n,k,mod;
int pre[MAXN+5][MAXK+5],suf[MAXN+5][MAXK+5];
int sum[MAXK+5],c1[MAXN+5],c2[MAXN+5];
int getsum(int l,int r){return (sum[r]-((!l)?0:sum[l-1])+mod)%mod;}
int main(){
scanf("%d%d%d",&n,&k,&mod);pre[0][0]=1;
for(int i=0;i<=k;i++) sum[i]=1;
for(int i=1;i<n;i++){
for(int j=0;j<=k;j++) pre[i][j]=getsum(j-i,j);
memset(sum,0,sizeof(sum));sum[0]=pre[i][0];
for(int j=1;j<=k;j++) sum[j]=(sum[j-1]+pre[i][j])%mod;
} suf[n][0]=1;
for(int i=0;i<=k;i++) sum[i]=1;
for(int i=n-1;~i;i--){
for(int j=0;j<=k;j++) suf[i][j]=getsum(j-i,j);
memset(sum,0,sizeof(sum));sum[0]=suf[i][0];
for(int j=1;j<=k;j++) sum[j]=(sum[j-1]+suf[i][j])%mod;
} c1[0]=c2[0]=pre[n-1][k];
for(int i=1;i<n;i++){
for(int j=0;j<=k;j++) c1[i]=(c1[i]+1ll*pre[i-1][j]*suf[i+1][k-j])%mod;
for(int j=0;j<=k-i;j++) c2[i]=(c2[i]+1ll*pre[i-1][j]*suf[i+1][k-i-j])%mod;
} for(int i=1;i<=n;i++){
int res=0;
for(int j=1;j<=n;j++){
if(j<=i) res=(res+c1[i-j])%mod;
else res=(res+c2[j-i])%mod;
} printf("%d%c",res," \n"[i==n]);
}
return 0;
}
洛谷 P5853 - [USACO19DEC]Tree Depth P(生成函数+背包)的更多相关文章
- 【题解】洛谷P1273 有线电视网(树上分组背包)
次元传送门:洛谷P1273 思路 一开始想的是普通树形DP 但是好像实现不大好 观摩了一下题解 是树上分组背包 设f[i][j]为以i为根的子树中取j个客户得到的总价值 我们可以以i为根有j组 在每一 ...
- 【洛谷】P1541 乌龟棋(四维背包dp)
题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家控制一个乌龟棋子从起 ...
- 【题解】洛谷P1941 [NOIP2014TG] 飞扬的小鸟(背包DP)
次元传送门:洛谷P1941 思路 从题意可知 在每个单位时间内 可以无限地向上飞 但是只能向下掉一次 所以我们可以考虑运用背包解决这道题 上升时 用完全背包 下降时 用01背包 设f[x][y]为在坐 ...
- 【题解】洛谷P1541 [NOIP2010TG] 乌龟棋(类似背包的DP)
题目来源:洛谷P1541 思路 类似背包的题 总之就是四种卡牌取的先后顺序不同导致的最终ans不同 所以我们用一个四维数组每一维分别表示第几种取了几张的最大分数 然后就是简单DP解决 代码 #incl ...
- 洛谷P5206 [WC2019] 数树(生成函数+容斥+矩阵树)
题面 传送门 前置芝士 矩阵树,基本容斥原理,生成函数,多项式\(\exp\) 题解 我也想哭了--orz rqy,orz shadowice 我们设\(T1,T2\)为两棵树,并定义一个权值函数\( ...
- [USACO19DEC]Tree Depth P
题意 求逆序对为\(k\)的\(n\)排列中,生成的笛卡尔数,每个位置的深度和.\(n\le 300\) 做法 设\(f_{k}\)为\(n\)排列中逆序对为\(k\)的个数,其生成函数为:\[\pr ...
- 【洛谷P4178】Tree
题面 题解 感觉和\(CDQ\)分治一样套路啊 首先,构建出点分树 对于每一层分治重心,求出它到子树中任意点的距离 然后\(two-pointers\)计算满足小于等于\(K\)的点对数目,加入答案 ...
- BZOJ2654 & 洛谷2619:tree——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=2654 https://www.luogu.org/problemnew/show/P2619 给你 ...
- 洛谷4178 BZOJ1468 Tree题解点分治
点分治的入门练习. 题目链接 BZOJ的链接(权限题) 关于点分治的思想我就不再重复了,这里重点说一下如何判重. 我们来看上图,假设我们去除了1节点,求出d[2]=1,d[3]=d[4]=2 假设k为 ...
随机推荐
- Stream中的Collector收集器原理
前言 Stream的基本操作因为平时工作中用得非常多(也能看到一些同事把Stream操作写得很丑陋),所以基本用法就不写文章记录了. 之所以能把Stream的操作写得很丑陋,完全是因为Stream底层 ...
- 【UE4 调试】C++ 常见编译 warnnings/errors
error LNK2019: unresolved external symbol "" referenced in function 描述 Link错误.无法解析的外部符号 解决 ...
- [no code][scrum meeting] Alpha 7
项目 内容 会议时间 2020-04-13 会议主题 OCR技术细节分析 会议时长 30min 参会人员 PM+OCR组成员 $( "#cnblogs_post_body" ).c ...
- 【二食堂】Beta - Scrum Meeting 1
Scrum Meeting 1 例会时间:5.13 18:30~18:50 进度情况 组员 当前进度 今日任务 李健 1. 查阅资料,解决划词勾选和右键菜单的问题issue2. 修复了Alpha阶段的 ...
- 对mongo文档的增删改操作
在mongo db 中增加.删除.修改文档有好多方法,这里简单记录一下我所知道的一些方法. 前置条件: 1.创建study数据库 use study; 2.创建persons集合,当第一次向pers ...
- 前端大牛带你了解JavaScript 函数式编程
前言 函数式编程在前端已经成为了一个非常热门的话题.在最近几年里,我们看到非常多的应用程序代码库里大量使用着函数式编程思想. 本文将略去那些晦涩难懂的概念介绍,重点展示在 JavaScript 中到底 ...
- 疯狂Java基础Day1
--每过一遍基础,都是一次提升! 太多遗忘了,慢慢补... 推一个Java学习教程--->b站搜:狂神说Java系列(排序完毕) 推荐原因:讲的不错,会涉及到底层,也会讲讲面试. 一.注释 主要 ...
- cf18B Platforms(仔细谨慎题)
题意: In one one-dimensional world there are n platforms. Platform with index k (platforms are numbere ...
- hdu 2955 Robberies(背包DP)
题意: 小偷去抢银行,他母亲很担心. 他母亲希望他被抓的概率真不超过P.小偷打算去抢N个银行,每个银行有两个值Mi.Pi,Mi:抢第i个银行所获得的财产 Pi:抢第i个银行被抓的概率 求最多能抢得多少 ...
- java性能优化常用工具jps、jstat、jinfo
jps:虚拟机进程状况工具 jps可以用来查看虚拟机进程,基本等同于ps -ef|grep java #查看jps的使用文档 [root@localhost script]# jps -help us ...