传送门

什么情况下两序列同构

对于两序列A[1,n],B[1,n]A[1,n],B[1,n]A[1,n],B[1,n],设fA(1,n)=pa,fB(1,n)=pbf_A(1,n)=p_a,f_B(1,n)=p_bfA​(1,n)=pa​,fB​(1,n)=pb​,

  • 若pa≠pbp_a\not=p_bpa​​=pb​,A,BA,BA,B一定不同构。
  • 若pa=pbp_a=p_bpa​=pb​,
    若A[1,pa−1]A[1,p_a-1]A[1,pa​−1]与B[1,pb−1]B[1,p_b-1]B[1,pb​−1]同构且A[pa+1,n]A[p_a+1,n]A[pa​+1,n]与B[pb+1,n]B[p_b+1,n]B[pb​+1,n]同构,则A[1,n],B[1,n]A[1,n],B[1,n]A[1,n],B[1,n]同构;
    否则A,BA,BA,B不同构。

由这个过程想到什么?笛卡尔树!
没错,两序列同构当且仅当它们的笛卡尔树形态相同

生成函数做法

引理证明:
A={X∣序列X长度为n,序列X中的每个数都是1到m内的整数}A=\{X| 序列X长度为n,序列X中的每个数都是1到m内的整数\}A={X∣序列X长度为n,序列X中的每个数都是1到m内的整数}
B={X∣序列X长度为n,序列X中的每个数都是1到m内的整数,且序列X中的最大值为m}B=\{X| 序列X长度为n,序列X中的每个数都是1到m内的整数,且序列X中的最大值为m\}B={X∣序列X长度为n,序列X中的每个数都是1到m内的整数,且序列X中的最大值为m}
C={X∣序列X长度为n,序列X中的每个数都是1到m内的整数,且所有1到m内的整数都在序列X中出现过}C=\{X| 序列X长度为n,序列X中的每个数都是1到m内的整数,且所有1到m内的整数都在序列 X 中出现过\}C={X∣序列X长度为n,序列X中的每个数都是1到m内的整数,且所有1到m内的整数都在序列X中出现过}
可以证明n≥mn\geq mn≥m时,A=B=CA=B=CA=B=C。

证明:
首先证明A=BA =BA=B。
对于AAA中任意一个序列XXX,若XXX中的最大值为ppp,那么把XXX中的每个数都加上m−pm−pm−p,得到序列YYY ,显然XXX和YYY同构,即X=YX=YX=Y 。YYY中最大值为mmm,即Y∈BY\in BY∈B。
对于任意 X∈AX \in AX∈A,均有X∈BX\in BX∈B,这说明A⊆BA\subseteq BA⊆B。而 B⊆AB\subseteq AB⊆A 是显然的,因此 A=BA=BA=B。

可以利用类似的方法证明 A=CA=CA=C。
对于AAA中任意一个序列XXX,可以在同构的前提下,保持不同权值的数之间的相对大小的同时,把权值相同的数按下标顺序替换成权值不同的数。这样在n≥mn\geq mn≥m时,通过上述替换,可以使XXX中出现过的数增加至mmm种。
对于任意X∈AX\in AX∈A,均有X∈CX\in CX∈C,这说明A⊆CA\subseteq CA⊆C。C⊆AC\subseteq AC⊆A 也是显然的,因此 A=CA =CA=C。

DP:
设f[i][j]f[i][j]f[i][j]表示n=i,m=jn=i,m=jn=i,m=j时的∣C∣|C|∣C∣,那么f[i][j]=∣C∣=∣A∣=∣B∣f[i][j]=|C|=|A|=|B|f[i][j]=∣C∣=∣A∣=∣B∣。
考虑计算∣B∣|B|∣B∣,那么最大值为jjj,枚举下标最小的jjj的下标,得到递推式:
f[i][j]=∑p=1if[p−1][j−1]×f[i−p][j]f[i][j]=\sum_{p=1}^{i}f[p-1][j-1]\times f[i-p][j]f[i][j]=p=1∑i​f[p−1][j−1]×f[i−p][j]
(把f[p−1][j−1]f[p-1][j-1]f[p−1][j−1]当∣A1∣|A_1|∣A1​∣,f[i−p][j]f[i-p][j]f[i−p][j]当∣A2∣|A_2|∣A2​∣)

引入生成函数:
设Fj(x)=∑i≥0f[i][j]xiF_j(x)=\sum_{i\geq 0}f[i][j]x^iFj​(x)=∑i≥0​f[i][j]xi,代入递推式有:
Fj(x)[xi]=∑p=1iFj−1(x)[xp−1]×Fj(x)[xi−p]F_j(x)[x^i]=\sum_{p=1}^{i}F_{j-1}(x)[x^{p-1}]\times F_j(x)[x^{i-p}]Fj​(x)[xi]=p=1∑i​Fj−1​(x)[xp−1]×Fj​(x)[xi−p]
Fj(x)[xi]=∑p=0i−1Fj−1(x)[xp]×Fj(x)[xi−1−p]F_j(x)[x^i]=\sum_{p=0}^{i-1}F_{j-1}(x)[x^{p}]\times F_j(x)[x^{i-1-p}]Fj​(x)[xi]=p=0∑i−1​Fj−1​(x)[xp]×Fj​(x)[xi−1−p]
Fj(x)[xi]=(Fj−1(x)×Fj(x))[xi−1]F_j(x)[x^i]=(F_{j-1}(x)\times F_j(x))[x^{i-1}]Fj​(x)[xi]=(Fj−1​(x)×Fj​(x))[xi−1]
平凡情况有f[0][j]=1f[0][j]=1f[0][j]=1。

所以Fj(x)=Fj(x)Fj−1(x)x+1F_j(x)=F_j(x)F_{j-1}(x)x+1Fj​(x)=Fj​(x)Fj−1​(x)x+1
所以Fj(x)=11−Fj−1(x)xF_j(x)=\frac{1}{1-F_{j-1}(x)x}Fj​(x)=1−Fj−1​(x)x1​

直接做似乎很不可做,但由这个式子我们知道FjF_jFj​可以分解为AjBj\frac{A_j}{B_j}Bj​Aj​​,其中Aj,BjA_j,B_jAj​,Bj​是两个次数界为O(j)O(j)O(j)的多项式,那么考虑求Aj,BjA_j,B_jAj​,Bj​:

AjBj=11−Aj−1Bj−1x\frac{A_j}{B_j}=\frac{1}{1-\frac{A_{j-1}}{B_{j-1}}x}Bj​Aj​​=1−Bj−1​Aj−1​​x1​
AjBj=Bj−1Bj−1−Aj−1x\frac{A_j}{B_j}=\frac{B_{j-1}}{B_{j-1}-A_{j-1}x}Bj​Aj​​=Bj−1​−Aj−1​xBj−1​​

于是得到Aj=Bj−1,Bj=Bj−1−Aj−1xA_j=B_{j-1},B_j=B_{j-1}-A_{j-1}xAj​=Bj−1​,Bj​=Bj−1​−Aj−1​x,将转移关系用矩阵来表示就得到:

[01−x1](Aj−1Bj−1)=(AjBj)\begin{bmatrix}0 & 1\\-x & 1 \end{bmatrix}\begin{pmatrix}A_{j-1}\\B_{j-1}\end{pmatrix}=\begin{pmatrix}A_j\\B_j\end{pmatrix}[0−x​11​](Aj−1​Bj−1​​)=(Aj​Bj​​)

那么可以通过矩阵快速幂来求Aj,BjA_j,B_jAj​,Bj​。但是直接在矩阵中用多项式进行计算会很麻烦,因此不妨考虑用单位根代入求点值,用IDFTIDFTIDFT插出多项式即可。复杂度O(nlogn)O(nlogn)O(nlogn)。

参考博客

卡特兰数做法

因为两序列同构当且仅当它们的笛卡尔树形态相同,所以原题就是问有多少棵不同形态的节点数为nnn的笛卡尔树满足要求。

为了满足题目中所给出的 “如果有多个最大值,取下标最小的” 的要求,规定笛卡尔树上的节点xxx满足:左儿子的值<x<x<x的值&&右儿子的值≤x\leq x≤x的值

根据上文引理的证明,
“序列中的每个数都是1到mmm内的整数,且所有111到mmm内的整数都在序列中出现过”的条件
等价于 “序列中的每个数都是1到mmm内的整数”,
所以一棵笛卡尔树有符合条件的填数方法,当且仅当 从根节点往下走,不存在一种走法,使得往左儿子走的次数>m−1>m−1>m−1(每往左儿子走一次,相当于权值 −1,需要有数可填)

考虑将"往左儿子走的次数≤m−1\leq m−1≤m−1"的条件进行转换,变为更容易处理的问题:
想到多叉树转二叉树的方法:节点xxx的左儿子为原树上xxx的儿子,右儿子为原树上xxx的兄弟
考虑把笛卡尔树这棵二叉树转回多叉树(存在转换后构不成一棵树的情况,需要新增一个虚点作为根节点),
“笛卡尔树上往左儿子走的次数≤m−1\leq m−1≤m−1” 等价于 “记虚点的深度为0,多叉树的深度要≤m\leq m≤m”。
问题变成统计 有n+1n+1n+1个节点,深度≤m\leq m≤m的不同形态的多叉树棵树

考虑树的括号表示,再稍微改一下定义

以这棵树为例,常规的括号表示法为1(2(4(8,9),5(10,11)),3(6(12),7)),我把它改成
从左到右遍历多叉树对应的括号序列(不算最外层根代表的那对括号),要求任何时候 左括号数量≥右括号数量左括号数量\geq 右括号数量左括号数量≥右括号数量(括号序列性质),左括号数量−右括号数量≤m左括号数量-右括号数量\leq m左括号数量−右括号数量≤m(树的深度≤m\leq m≤m)

把统计合法的括号序列个数 转化为 统计折线数量
从左到右遍历括号序列,每遍历到一个括号,xxx坐标+1,如果遍历到的是左括号则yyy坐标+1,遍历到的是右括号则yyy坐标-1。起点为(0,0)(0,0)(0,0),终点为(2n,0)(2n,0)(2n,0)。由于对括号序列的限制,行走过程中不能经过y=−1y=-1y=−1,y=m+1y=m+1y=m+1这两条直线。

原问题转为 统计从(0,0)(0,0)(0,0)走到(2n,0)(2n,0)(2n,0),每次x+1x+1x+1,y+1或−1y+1或-1y+1或−1,不经过y=−1y=-1y=−1,y=m+1y=m+1y=m+1这两条直线的合法方案数。

先简化问题:只限制折线不能经过y=−1y=-1y=−1,不限制其不能经过y=m+1y=m+1y=m+1

记A(x1,y1)→(x2,y2)A_{(x1,y1)\to(x2,y2)}A(x1,y1)→(x2,y2)​为从(x1,y1)(x1,y1)(x1,y1)走到(x2,y2)(x2,y2)(x2,y2),不考虑是否经过某些直线的方案数,
B(x1,y1)→(x2,y2)B_{(x1,y1)\to(x2,y2)}B(x1,y1)→(x2,y2)​为从(x1,y1)(x1,y1)(x1,y1)走到(x2,y2)(x2,y2)(x2,y2),经过y=−1y=-1y=−1的方案数,
C(x1,y1)→(x2,−1)C_{(x1,y1)\to(x2,-1)}C(x1,y1)→(x2,−1)​为从(x1,y1)(x1,y1)(x1,y1)走到(x2,−1)(x2,-1)(x2,−1),在(x2,−1)(x2,-1)(x2,−1)第一次经过y=−1y=-1y=−1的方案数。

A(x1,y1)→(x2,y2)=Cx2−x1x2−x1+y2−y12A_{(x1,y1)\to (x2,y2)}=C_{x2-x1}^{\frac{x2-x1+y2-y1}{2}}A(x1,y1)→(x2,y2)​=Cx2−x12x2−x1+y2−y1​​(相当于在x2−x1x2-x1x2−x1步中选x2−x1+y2−y12\frac{x2-x1+y2-y1}{2}2x2−x1+y2−y1​步令yyy坐标+1)

考虑容斥,简化版问题的答案为A(0,0)→(2n,0)−B(0,0)→(2n,0)A_{(0,0)\to(2n,0)}-B_{(0,0)\to(2n,0)}A(0,0)→(2n,0)​−B(0,0)→(2n,0)​
B(0,0)→(2n,0)=∑p=12n−1C(0,0)→(p,−1)×A(p,−1)→(2n,0)B_{(0,0)\to(2n,0)}=\sum_{p=1}^{2n-1}C_{(0,0)\to(p,-1)}\times A_{(p,-1)\to(2n,0)}B(0,0)→(2n,0)​=p=1∑2n−1​C(0,0)→(p,−1)​×A(p,−1)→(2n,0)​
设s′s's′与s(0,0)s(0,0)s(0,0)关于y=−1y=-1y=−1对称,根据对称性C(0,0)→(p,−1)=Cs′→(p,−1)C_{(0,0)\to(p,-1)}=C_{s'\to (p,-1)}C(0,0)→(p,−1)​=Cs′→(p,−1)​
所以
B(0,0)→(2n,0)=∑p=12n−1Cs′→(p,−1)×A(p,−1)→(2n,0)B_{(0,0)\to(2n,0)}=\sum_{p=1}^{2n-1}C_{s'\to (p,-1)}\times A_{(p,-1)\to(2n,0)}B(0,0)→(2n,0)​=p=1∑2n−1​Cs′→(p,−1)​×A(p,−1)→(2n,0)​
等式右侧那坨式子的组合意义就是As′→(2n,0)A_{s'\to(2n,0)}As′→(2n,0)​
所以
B(0,0)→(2n,0)=As′→(2n,0)B_{(0,0)\to(2n,0)}=A_{s'\to(2n,0)}B(0,0)→(2n,0)​=As′→(2n,0)​

再考虑简化前的问题怎么做:

若要计算 “经过若干次y=m+1y=m+1y=m+1,再经过若干次y=−1y=−1y=−1,再经过若干次y=m+1y=m+1y=m+1,再.........” 的折线数量,则把起点(0,0)(0,0)(0,0)关于y=m+1y=m+1y=m+1对称,再关于y=−1y=−1y=−1对称,再关于y=m+1y=m+1y=m+1对称,再......... 所求折线数量即为 最终得到的起点到(2n,0)(2n,0)(2n,0),不考虑是否经过某些直线的折线数量。

折线先经过y=−1y=-1y=−1的情况同理。

还是考虑容斥,容斥系数就是(−1)对称次数(-1)^{对称次数}(−1)对称次数

参考博客

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
const int mod=998244353;
int n,m,fac[N<<1],ifac[N<<1];
int C(int n,int m){return (ll)fac[n]*ifac[m]%mod*ifac[n-m]%mod;
}
int main(){scanf("%d%d",&n,&m);if(m>n){puts("0");return 0;}fac[0]=fac[1]=ifac[0]=ifac[1]=1;for(int i=2;i<=n*2;i++) fac[i]=(ll)fac[i-1]*i%mod,ifac[i]=(ll)(mod-mod/i)*ifac[mod%i]%mod;for(int i=2;i<=n*2;i++) ifac[i]=(ll)ifac[i-1]*ifac[i]%mod;int ans=C(n*2,n);for(int i=0,x=0;;i++){if(i&1) x=-2-x;else x=(m+1)*2-x;if(abs(x)>n*2) break;if(i&1) (ans+=C(n*2,(n*2-x)/2))%=mod;else (ans+=mod-C(n*2,(n*2-x)/2))%=mod;}for(int i=0,x=0;;i++){if(i&1) x=(m+1)*2-x;else x=-2-x;if(abs(x)>n*2) break;if(i&1) (ans+=C(n*2,(n*2-x)/2))%=mod;else (ans+=mod-C(n*2,(n*2-x)/2))%=mod;}printf("%d\n", ans);return 0;
}

[集训队作业2018] count(笛卡尔树,生成函数,卡特兰数)相关推荐

  1. 【UOJ#450】【集训队作业2018】复读机(生成函数,单位根反演)

    [UOJ#450][集训队作业2018]复读机(生成函数,单位根反演) 题面 UOJ 题解 似乎是\(\mbox{Anson}\)爷的题. \(d=1\)的时候,随便怎么都行,答案就是\(k^n\). ...

  2. 「LOJ2474」「2018 集训队互测」北校门外的未来-笛卡尔树及其扩展+LCT

    Description 链接 Solution 对于一棵树 TTT,定义其的笛卡尔树 C(T)C(T)C(T) 满足: 堆性质,即祖先的权值(本题中为标号)一定大于子孙的权值. 搜索树性质,即任意子树 ...

  3. UOJ#449. 【集训队作业2018】喂鸽子

    #449. [集训队作业2018]喂鸽子 DP好题 法一:min-max容斥 处理前m个,最快吃饱的鸽子期望的时间 根据期望的定义 考虑每个方案数的概率*期望次数 枚举前m个用了x个,概率都是(1/m ...

  4. HDU 4125 Moles 笛卡尔树 + kmp

    题意:有n(1<=n<=600000)个鼹鼠挖洞,每个鼹鼠有给定权值,挖的洞是一颗二叉树(左边的鼹鼠权值都比当前鼹鼠小,右边的鼹鼠权值比当前鼹鼠大), 也要按照鼹鼠的出场顺序挖洞,在形成的 ...

  5. hdu6305(笛卡尔树/分治)

    这道需要注意到一点..就是如果询问的区间如果覆盖了最大数,那么rmq一定是确定的..故以这个最大数为分界,左右2个区间是完全独立的..因此就可以采用分治的做法去做..聪明的汪聚聚已经实现.. 然后dl ...

  6. UOJ#418. 【集训队作业2018】三角形

    #418. [集训队作业2018]三角形 和三角形没有关系 只要知道儿子放置的顺序,就可以直接模拟了 记录历史最大值 用一个pair(a,b):之后加上a个,期间最大值为增加b个 合并? A1+A2= ...

  7. HDU - 6305 RMQ Similar Sequence(笛卡尔树)

    http://acm.hdu.edu.cn/showproblem.php?pid=6305 题目 对于A,B两个序列,任意的l,r,如果RMQ(A,l,r)=RMQ(B,l,r),B序列里的数为[0 ...

  8. [算法学习] 线段树,树状数组,数堆,笛卡尔树

    都是树的变种,用途不同 [线段树 Interval Tree] 区间管理,是一种平衡树 可看做是对一维数组的索引进行管理.一维数组不需要是排序好的 深度不超过logL 任一个区间(线段)都分成不超过2 ...

  9. 洛谷 - P4755 Beautiful Pair(笛卡尔树+主席树)

    题目链接:点击查看 题目大意:给出一个长度为 n 的数列 a,现在一个数对 ( i , j ) 如果满足 a[ i ] * a[ j ] <=max( a[ i ] ~ a[ j ] ),则称其 ...

最新文章

  1. html选择按钮selected,HTML Option defaultSelected用法及代码示例
  2. 《系统集成项目管理工程师》必背100个知识点-48质量控制的老七工具和新七工具...
  3. 「Android」 详细全面的基于vue2.0Weex接入过程(Android视角)
  4. Mysql(7)——auto_increment简介
  5. HBA driver for linux
  6. sim800c GPRS模块的透传模式
  7. tensorflow随笔——交叉熵公式推导
  8. python中str与bytes
  9. WinForm CefSharp 笔记一(入门篇)
  10. 「Windows Bug」Window 系统下双网卡内外网冲突
  11. 用3DSMAX制作室内效果图的九大步骤
  12. 目标检测Anchor是什么?怎么科学设置?人人都能彻底搞懂的Anchor深度解析
  13. HTML5 新特性: Web Worker 的创建与使用(webpack + TS 环境)
  14. STM8 的汇编学习
  15. iOS发展史:从iPhone OS 1.0到iOS10 终于支持骚扰拦截了
  16. PCB及电路抗干扰措施
  17. tpwr886n路由器设置虚拟服务器,tl-wr886n路由器设置步骤图解 | 192路由网
  18. win10删除设备和驱动器中多余的软件图标
  19. javascript常用方法 – String
  20. html列表横向变纵向,手机版利用 CSS 将横向表格转换成竖向列表显示

热门文章

  1. toast弹窗_Android 开发(一):Toast弹窗与获取控件的值
  2. php获取域名方法,PHP实现获取域名的方法小结
  3. 怎样用python批量处理文件夹_python批量处理文件或文件夹
  4. java实用教程——组件及事件处理——对话框(dialog)
  5. leetcode455. 分发饼干
  6. poj2182 Lost Cows-线段树
  7. 高等数学上-赵立军-北京大学出版社-题解-练习2.3
  8. 算法-排序-快速排序(包含多种快速排序)
  9. Largest Rectangle in a Histogram (动态规划+奇思妙想单调栈)求最大矩状图面积
  10. HashMap实现LRU(最近最少使用)缓存更新算法