日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

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

發(fā)布時(shí)間:2023/12/3 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [集训队作业2018] count(笛卡尔树,生成函数,卡特兰数) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

傳送門

什么情況下兩序列同構(gòu)

對(duì)于兩序列A[1,n],B[1,n]A[1,n],B[1,n]A[1,n],B[1,n],設(shè)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一定不同構(gòu)。
  • 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]同構(gòu)且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]同構(gòu),則A[1,n],B[1,n]A[1,n],B[1,n]A[1,n],B[1,n]同構(gòu);
    否則A,BA,BA,B不同構(gòu)。

由這個(gè)過(guò)程想到什么?笛卡爾樹(shù)!
沒(méi)錯(cuò),兩序列同構(gòu)當(dāng)且僅當(dāng)它們的笛卡爾樹(shù)形態(tài)相同

生成函數(shù)做法

引理證明:
A={X∣序列X長(zhǎng)度為n,序列X中的每個(gè)數(shù)都是1到m內(nèi)的整數(shù)}A=\{X| 序列X長(zhǎng)度為n,序列X中的每個(gè)數(shù)都是1到m內(nèi)的整數(shù)\}A={XX長(zhǎng)n,X個(gè)數(shù)1m內(nèi)數(shù)}
B={X∣序列X長(zhǎng)度為n,序列X中的每個(gè)數(shù)都是1到m內(nèi)的整數(shù),且序列X中的最大值為m}B=\{X| 序列X長(zhǎng)度為n,序列X中的每個(gè)數(shù)都是1到m內(nèi)的整數(shù),且序列X中的最大值為m\}B={XX長(zhǎng)n,X個(gè)數(shù)1m內(nèi)數(shù)Xm}
C={X∣序列X長(zhǎng)度為n,序列X中的每個(gè)數(shù)都是1到m內(nèi)的整數(shù),且所有1到m內(nèi)的整數(shù)都在序列X中出現(xiàn)過(guò)}C=\{X| 序列X長(zhǎng)度為n,序列X中的每個(gè)數(shù)都是1到m內(nèi)的整數(shù),且所有1到m內(nèi)的整數(shù)都在序列 X 中出現(xiàn)過(guò)\}C={XX長(zhǎng)n,X個(gè)數(shù)1m內(nèi)數(shù)1m內(nèi)數(shù)X現(xiàn)過(guò)}
可以證明n≥mn\geq mnm時(shí),A=B=CA=B=CA=B=C

證明:
首先證明A=BA =BA=B
對(duì)于AAA中任意一個(gè)序列XXX,若XXX中的最大值為ppp,那么把XXX中的每個(gè)數(shù)都加上m?pm?pm?p,得到序列YYY ,顯然XXXYYY同構(gòu),即X=YX=YX=YYYY中最大值為mmm,即Y∈BY\in BYB
對(duì)于任意 X∈AX \in AXA,均有X∈BX\in BXB,這說(shuō)明A?BA\subseteq BA?B。而 B?AB\subseteq AB?A 是顯然的,因此 A=BA=BA=B

可以利用類似的方法證明 A=CA=CA=C
對(duì)于AAA中任意一個(gè)序列XXX,可以在同構(gòu)的前提下,保持不同權(quán)值的數(shù)之間的相對(duì)大小的同時(shí),把權(quán)值相同的數(shù)按下標(biāo)順序替換成權(quán)值不同的數(shù)。這樣在n≥mn\geq mnm時(shí),通過(guò)上述替換,可以使XXX中出現(xiàn)過(guò)的數(shù)增加至mmm種。
對(duì)于任意X∈AX\in AXA,均有X∈CX\in CXC,這說(shuō)明A?CA\subseteq CA?CC?AC\subseteq AC?A 也是顯然的,因此 A=CA =CA=C

DP:
設(shè)f[i][j]f[i][j]f[i][j]表示n=i,m=jn=i,m=jn=i,m=j時(shí)的∣C∣|C|C,那么f[i][j]=∣C∣=∣A∣=∣B∣f[i][j]=|C|=|A|=|B|f[i][j]=C=A=B
考慮計(jì)算∣B∣|B|B,那么最大值為jjj,枚舉下標(biāo)最小的jjj的下標(biāo),得到遞推式:
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=1i?f[p?1][j?1]×f[i?p][j]
(把f[p?1][j?1]f[p-1][j-1]f[p?1][j?1]當(dāng)∣A1∣|A_1|A1?f[i?p][j]f[i-p][j]f[i?p][j]當(dāng)∣A2∣|A_2|A2?)

引入生成函數(shù):
設(shè)Fj(x)=∑i≥0f[i][j]xiF_j(x)=\sum_{i\geq 0}f[i][j]x^iFj?(x)=i0?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=1i?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=0i?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?

直接做似乎很不可做,但由這個(gè)式子我們知道FjF_jFj?可以分解為AjBj\frac{A_j}{B_j}Bj?Aj??,其中Aj,BjA_j,B_jAj?,Bj?是兩個(gè)次數(shù)界為O(j)O(j)O(j)的多項(xiàng)式,那么考慮求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,將轉(zhuǎn)移關(guān)系用矩陣來(lái)表示就得到:

[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??)

那么可以通過(guò)矩陣快速冪來(lái)求Aj,BjA_j,B_jAj?,Bj?。但是直接在矩陣中用多項(xiàng)式進(jìn)行計(jì)算會(huì)很麻煩,因此不妨考慮用單位根代入求點(diǎn)值,用IDFTIDFTIDFT插出多項(xiàng)式即可。復(fù)雜度O(nlogn)O(nlogn)O(nlogn)

參考博客

卡特蘭數(shù)做法

因?yàn)?strong>兩序列同構(gòu)當(dāng)且僅當(dāng)它們的笛卡爾樹(shù)形態(tài)相同,所以原題就是問(wèn)有多少棵不同形態(tài)的節(jié)點(diǎn)數(shù)為nnn的笛卡爾樹(shù)滿足要求。

為了滿足題目中所給出的 “如果有多個(gè)最大值,取下標(biāo)最小的” 的要求,規(guī)定笛卡爾樹(shù)上的節(jié)點(diǎn)xxx滿足:左兒子的值<x<x<x的值&&右兒子的值≤x\leq xx的值

根據(jù)上文引理的證明,
“序列中的每個(gè)數(shù)都是1到mmm內(nèi)的整數(shù),且所有111mmm內(nèi)的整數(shù)都在序列中出現(xiàn)過(guò)”的條件
等價(jià)于 “序列中的每個(gè)數(shù)都是1到mmm內(nèi)的整數(shù)”,
所以一棵笛卡爾樹(shù)有符合條件的填數(shù)方法,當(dāng)且僅當(dāng) 從根節(jié)點(diǎn)往下走,不存在一種走法,使得往左兒子走的次數(shù)>m?1>m?1>m?1(每往左兒子走一次,相當(dāng)于權(quán)值 ?1,需要有數(shù)可填)

考慮將"往左兒子走的次數(shù)≤m?1\leq m?1m?1"的條件進(jìn)行轉(zhuǎn)換,變?yōu)楦菀滋幚淼膯?wèn)題:
想到多叉樹(shù)轉(zhuǎn)二叉樹(shù)的方法:節(jié)點(diǎn)xxx的左兒子為原樹(shù)上xxx的兒子,右兒子為原樹(shù)上xxx的兄弟
考慮把笛卡爾樹(shù)這棵二叉樹(shù)轉(zhuǎn)回多叉樹(shù)(存在轉(zhuǎn)換后構(gòu)不成一棵樹(shù)的情況,需要新增一個(gè)虛點(diǎn)作為根節(jié)點(diǎn)),
“笛卡爾樹(shù)上往左兒子走的次數(shù)≤m?1\leq m?1m?1” 等價(jià)于 “記虛點(diǎn)的深度為0,多叉樹(shù)的深度要≤m\leq mm”。
問(wèn)題變成統(tǒng)計(jì) n+1n+1n+1個(gè)節(jié)點(diǎn),深度≤m\leq mm的不同形態(tài)的多叉樹(shù)棵樹(shù)

考慮樹(shù)的括號(hào)表示,再稍微改一下定義

以這棵樹(shù)為例,常規(guī)的括號(hào)表示法為1(2(4(8,9),5(10,11)),3(6(12),7)),我把它改成
從左到右遍歷多叉樹(shù)對(duì)應(yīng)的括號(hào)序列(不算最外層根代表的那對(duì)括號(hào)),要求任何時(shí)候 左括號(hào)數(shù)量≥右括號(hào)數(shù)量左括號(hào)數(shù)量\geq 右括號(hào)數(shù)量號(hào)數(shù)號(hào)數(shù)(括號(hào)序列性質(zhì)),左括號(hào)數(shù)量?右括號(hào)數(shù)量≤m左括號(hào)數(shù)量-右括號(hào)數(shù)量\leq m號(hào)數(shù)?號(hào)數(shù)m(樹(shù)的深度≤m\leq mm

把統(tǒng)計(jì)合法的括號(hào)序列個(gè)數(shù) 轉(zhuǎn)化為 統(tǒng)計(jì)折線數(shù)量
從左到右遍歷括號(hào)序列,每遍歷到一個(gè)括號(hào),xxx坐標(biāo)+1,如果遍歷到的是左括號(hào)則yyy坐標(biāo)+1,遍歷到的是右括號(hào)則yyy坐標(biāo)-1。起點(diǎn)為(0,0)(0,0)(0,0),終點(diǎn)為(2n,0)(2n,0)(2n,0)。由于對(duì)括號(hào)序列的限制,行走過(guò)程中不能經(jīng)過(guò)y=?1y=-1y=?1y=m+1y=m+1y=m+1這兩條直線。

原問(wèn)題轉(zhuǎn)為 統(tǒng)計(jì)從(0,0)(0,0)(0,0)走到(2n,0)(2n,0)(2n,0),每次x+1x+1x+1y+1或?1y+1或-1y+1?1,不經(jīng)過(guò)y=?1y=-1y=?1y=m+1y=m+1y=m+1這兩條直線的合法方案數(shù)。

先簡(jiǎn)化問(wèn)題:只限制折線不能經(jīng)過(guò)y=?1y=-1y=?1,不限制其不能經(jīng)過(guò)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),不考慮是否經(jīng)過(guò)某些直線的方案數(shù),
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),經(jīng)過(guò)y=?1y=-1y=?1的方案數(shù),
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)第一次經(jīng)過(guò)y=?1y=-1y=?1的方案數(shù)。

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??(相當(dāng)于在x2?x1x2-x1x2?x1步中選x2?x1+y2?y12\frac{x2-x1+y2-y1}{2}2x2?x1+y2?y1?步令yyy坐標(biāo)+1)

考慮容斥,簡(jiǎn)化版問(wèn)題的答案為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=12n?1?C(0,0)(p,?1)?×A(p,?1)(2n,0)?
設(shè)s′s'ss(0,0)s(0,0)s(0,0)關(guān)于y=?1y=-1y=?1對(duì)稱,根據(jù)對(duì)稱性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=12n?1?Cs(p,?1)?×A(p,?1)(2n,0)?
等式右側(cè)那坨式子的組合意義就是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)?

再考慮簡(jiǎn)化前的問(wèn)題怎么做:

若要計(jì)算 “經(jīng)過(guò)若干次y=m+1y=m+1y=m+1,再經(jīng)過(guò)若干次y=?1y=?1y=?1,再經(jīng)過(guò)若干次y=m+1y=m+1y=m+1,再.........” 的折線數(shù)量,則把起點(diǎn)(0,0)(0,0)(0,0)關(guān)于y=m+1y=m+1y=m+1對(duì)稱,再關(guān)于y=?1y=?1y=?1對(duì)稱,再關(guān)于y=m+1y=m+1y=m+1對(duì)稱,再......... 所求折線數(shù)量即為 最終得到的起點(diǎn)到(2n,0)(2n,0)(2n,0),不考慮是否經(jīng)過(guò)某些直線的折線數(shù)量。

折線先經(jīng)過(guò)y=?1y=-1y=?1的情況同理。

還是考慮容斥,容斥系數(shù)就是(?1)對(duì)稱次數(shù)(-1)^{對(duì)稱次數(shù)}(?1)對(duì)數(shù)

參考博客

#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; } 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的[集训队作业2018] count(笛卡尔树,生成函数,卡特兰数)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。