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

传送门

什么情况下两序列同构

对于两序列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=pbA,BA,BA,B一定不同构。
  • pa=pbp_a=p_bpa=pb
    A[1,pa−1]A[1,p_a-1]A[1,pa1]B[1,pb−1]B[1,p_b-1]B[1,pb1]同构且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={XXn,X1m}
B={X∣序列X长度为n,序列X中的每个数都是1到m内的整数,且序列X中的最大值为m}B=\{X| 序列X长度为n,序列X中的每个数都是1到m内的整数,且序列X中的最大值为m\}B={XXn,X1mXm}
C={X∣序列X长度为n,序列X中的每个数都是1到m内的整数,且所有1到m内的整数都在序列X中出现过}C=\{X| 序列X长度为n,序列X中的每个数都是1到m内的整数,且所有1到m内的整数都在序列 X 中出现过\}C={XXn,X1m1mX}
可以证明n≥mn\geq mnm时,A=B=CA=B=CA=B=C

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

可以利用类似的方法证明 A=CA=CA=C
对于AAA中任意一个序列XXX,可以在同构的前提下,保持不同权值的数之间的相对大小的同时,把权值相同的数按下标顺序替换成权值不同的数。这样在n≥mn\geq mnm时,通过上述替换,可以使XXX中出现过的数增加至mmm种。
对于任意X∈AX\in AXA,均有X∈CX\in CXC,这说明A⊆CA\subseteq CACC⊆AC\subseteq ACA 也是显然的,因此 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=1if[p1][j1]×f[ip][j]
(把f[p−1][j−1]f[p-1][j-1]f[p1][j1]∣A1∣|A_1|A1f[i−p][j]f[i-p][j]f[ip][j]∣A2∣|A_2|A2)

引入生成函数:
Fj(x)=∑i≥0f[i][j]xiF_j(x)=\sum_{i\geq 0}f[i][j]x^iFj(x)=i0f[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=1iFj1(x)[xp1]×Fj(x)[xip]
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=0i1Fj1(x)[xp]×Fj(x)[xi1p]
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]=(Fj1(x)×Fj(x))[xi1]
平凡情况有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)Fj1(x)x+1
所以Fj(x)=11−Fj−1(x)xF_j(x)=\frac{1}{1-F_{j-1}(x)x}Fj(x)=1Fj1(x)x1

直接做似乎很不可做,但由这个式子我们知道FjF_jFj可以分解为AjBj\frac{A_j}{B_j}BjAj,其中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}BjAj=1Bj1Aj1x1
AjBj=Bj−1Bj−1−Aj−1x\frac{A_j}{B_j}=\frac{B_{j-1}}{B_{j-1}-A_{j-1}x}BjAj=Bj1Aj1xBj1

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

[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}[0x11](Aj1Bj1)=(AjBj)

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

参考博客

卡特兰数做法

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

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

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

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

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

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

原问题转为 统计从(0,0)(0,0)(0,0)走到(2n,0)(2n,0)(2n,0),每次x+1x+1x+1y+1或−1y+1或-1y+11,不经过y=−1y=-1y=1y=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)=Cx2x12x2x1+y2y1(相当于在x2−x1x2-x1x2x1步中选x2−x1+y2−y12\frac{x2-x1+y2-y1}{2}2x2x1+y2y1步令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=12n1C(0,0)(p,1)×A(p,1)(2n,0)
s′s'ss(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=12n1Cs(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;
}

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

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

相关文章

P4016 负载平衡问题

文章目录题目描述题解&#xff1a;方法一&#xff1a;代码&#xff1a;方法二&#xff1a;P4016 负载平衡问题题目描述 G 公司有 n 个沿铁路运输线环形排列的仓库&#xff0c;每个仓库存储的货物数量不等。如何用最少搬运量可以使 n 个仓库的库存数量相同。搬运货物时&#xff…

Ocelot简易教程(二)之快速开始2

为什么这篇的标题叫“Ocelot简易教程&#xff08;二&#xff09;之快速开始2”呢&#xff0c;因为很多朋友跟我说上一篇“ Ocelot简易教程&#xff08;二&#xff09;之快速开始1”内容太少了&#xff0c;只是简单介绍Ocelot的一些简单配置&#xff0c;让Ocelot能跑起来&#x…

.NET的前世今生与将来

笔者注谨以此文纪念我敬重的2016年9月17日去世的 装配脑袋 逝世两周年让大家久等了&#xff0c;前后花了1年的时间&#xff0c;几经改版&#xff0c;终于完成撰写了一万字长文&#xff0c;回顾和展望.NET这16年来的成功与失败。最终能成文是因为我给自己承诺必须赶在 装配脑袋 …

P4011 孤岛营救问题

P4011 孤岛营救问题 文章目录输入输出样例题意&#xff1a;题解&#xff1a;代码&#xff1a;输入输出样例 输入 4 4 9 9 1 2 1 3 2 1 2 2 2 0 2 1 2 2 0 2 1 3 1 0 2 3 3 3 0 2 4 3 4 1 3 2 3 3 0 3 3 4 3 0 4 3 4 4 0 2 2 1 2 4 2 1输出 14题意&#xff1a; (原题太长我就…

[NOI2014] 起床困难综合症(二进制,贪心)

#include<bits/stdc.h> int n,m,ans,x,a10,a2-1; //-1的补码:11111111111... char str[5]; int main(){scanf("%d%d",&n,&m);while(n--){scanf("%s%d",str,&x);if(str[0]A) a1&x, a2&x;if(str[0]X) a1^x, a2^x;if(str[0]O) a1|…

P4015 运输问题

P4015 运输问题 文章目录题目描述&#xff1a;输入格式&#xff1a;输出格式&#xff1a;输入输出样例&#xff1a;题解&#xff1a;代码&#xff1a;题目描述&#xff1a; 输入格式&#xff1a; 输出格式&#xff1a; 两行分别输出最小运输费用和最大运输费用。 输入输出样例…

NetCore使用Jwtbearer给WebAPI添加访问控制

现在JWT代替session来做访问控制已经成为大部分webapi的做法&#xff0c;今天我们也来尝试一下WebAPI使用NetCore2.1创建,无身份认证信息nuget安装包IdentityModel 选择稳定版3.9.0Microsoft.AspNetCore.Authorization 版本2.1.1Microsoft.AspNetCore.Authentication.JwtBearer…

图论复习——网络流

最大流 与 最小费用最大流 Blog 有上下界网络流 Blog 最小割 Blog 模拟费用流 CF724E Goods transportation 摘自此Blog 建图优化 若同一行或者同一列的点互相可达&#xff0c;那么其实不需要两两连边&#xff0c;只需要对于每行和每列建一个辅助节点作为中转 [ARC…

离散大创项目——图片识别笔记

1.我才知道ainput()读入的竟然是字符串。。。还要强制转化成int型&#xff0c;这玩意搞了我好久 2.对照片进行裁剪&#xff0c;将照片周围多余的白色部分去除&#xff08;也就是让图像尽可能撑满整个框&#xff09; 由上一张裁成下一张 from PIL import Image import os SCA…

最小割小记

参考博客&#xff1a;最小割浅谈 关于最小割 常用描述 表述一&#xff1a;删去若干条边使得源点到汇点不连通&#xff0c;求删边的权值和的最小可能值。 表述二&#xff1a;将点集分为(S,T)(S,T)(S,T)&#xff0c;记所有从SSS中出发到TTT中的边的权值和为c(S,T)c(S,T)c(S,T)&a…

斐波那契数列求法

文章目录求斐波那切数列的几个方法&#xff1a;经典做法&#xff1a;递推&#xff1a;动态规划矩阵快速幂原理&#xff1a;代码&#xff1a;例题&#xff1a;模拟过程求斐波那切数列的几个方法&#xff1a; 经典做法&#xff1a; 众所周知&#xff1a;斐波那契数列的定义是f(…

ASP.Net Core2.1中的HttpClientFactory系列一

引言&#xff1a;ASP.NET Core2.1 中出现了一个新的 HttpClientFactory 功能, 它有助于解决开发人员在使用 HttpClient 实例从其应用程序中访问外部 web 资源时可能遇到的一些常见问题。关于HttpClientFactory 到底解决了那些HttpClient的严重问题&#xff0c;下面是我罗列出来…

最大子矩阵(普通和01)

文章目录普通矩阵&#xff08;单个矩阵值为任何数&#xff09;最大子段和扩展到二维情况01矩阵&#xff08;单个矩阵值为0或1&#xff09;代码&#xff1a;普通矩阵&#xff08;单个矩阵值为任何数&#xff09; 例题&#xff1a;POJ 1074 求出其中最大的子矩阵 答案是&#x…

自动化流程开源框架BotSharp

BotSharp是一款为方便构建智能对话机器人平台而开发的开源框架&#xff0c;最大的特点是所有模型算法都是基于.NET Core开发实现&#xff0c;甚至最基本的Penn Treebank分词标准&#xff0c;都重新用C#实现了。在机器学习python占绝对优势的时代算是不可多得的项目。该项目涉及…

积极参与开源项目,促进.NET Core生态社区发展

今天早上在微信群里聊天聊到百度的SDK 已经支持.NET Core, 百度已经在3月份就支持了&#xff0c;想起当时还是我在他们的github上提的issue&#xff1a; https://github.com/Baidu-AIP/dotnet-sdk/issues/3。.NET Core生态社区的发展已经四年多时间&#xff0c;日趋完善&#x…

Service Fabric 与Ocelot 的集成

概要云应用程序通常都需要使用前端网关&#xff0c;为用户、设备或其他应用程序提供同一个入口点。 在 Service Fabric 中&#xff0c;网关可以是任意无状态服务&#xff08;如 ASP.NET Core 应用程序&#xff09; 。本文介绍了如何将Ocelot用作 Service Fabric 应用程序的网关…

图论复习——最短路

知识点 最短路径算法 最短路径树 每个点uuu的父亲为使uuu得到最短距离的前驱节点&#xff0c;若有多个&#xff0c;则取任意一个。 题目 CF449B Jzzhu and Cities Blog CF464E The Classic Problem Blog [XSY3888] 传送门 对每个点uuu&#xff0c;记d(u)d(u)d(u)表示uuu…

T-Dongle-S3开发笔记——创建工程

创建Hello world工程 打开命令面板 方法1&#xff1a;查看->命令面板 方法2&#xff1a;按F1 选择ESP-IDF:展示示例项目 创建helloworld 选择串口 选择芯片 至此可以编译下载运行了 运行后打印的信息显示flash只有2M。但是板子上电flash是W25Q32 4MB的吗 16M-bit

hdu 1576 A/B

文章目录题目&#xff1a;题解&#xff1a;代码&#xff1a;hdu 1576题目&#xff1a; 要求(A/B)%9973&#xff0c;但由于A很大&#xff0c;我们只给出n(nA%9973)(我们给定的A必能被B整除&#xff0c;且gcd(B,9973) 1)。 Input 数据的第一行是一个T&#xff0c;表示有T组数据。…

ASP.NET Core 中断请求了解一下(翻译)

本文所讲方式仅适用于托管在Kestrel Server中的应用。如果托管在IIS和IIS Express上时&#xff0c;ASP.NET Core Module(ANCM)并不会告诉ASP.NET Core在客户端断开连接时中止请求。但可喜的是&#xff0c;ANCM预计在.NET Core 2.2中会完善这一机制。1. 引言假设有一个耗时的Act…