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

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

生活随笔

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

编程问答

[Catalan数三连]网格有趣的数列树屋阶梯

發(fā)布時(shí)間:2024/9/5 编程问答 78 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [Catalan数三连]网格有趣的数列树屋阶梯 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

?

如何讓孩子愛(ài)上打表

Catalan數(shù)

Catalan數(shù)是組合數(shù)學(xué)中一個(gè)常出現(xiàn)在各種計(jì)數(shù)問(wèn)題中的數(shù)列。

以比利時(shí)的數(shù)學(xué)家歐仁·查理·卡塔蘭 (1814–1894)的名字來(lái)命名。

先丟個(gè)公式(設(shè)第n項(xiàng)為$h_n$):

$h_n=h_0*h_{n-1}+h_1*h_{n-2}+...+h_{n-1}*h_0,(n \ge 2)$

$h_n=\frac{h_{n-1}*(4n-2)}{n+1}$

$h_n=C_{2n}^n-C_{2n}^{n-1}=\frac{C_{2n}^n}{n+1}$

?

應(yīng)用

出棧次序是卡特蘭數(shù)的一個(gè)應(yīng)用。

我們將入棧視為+1,出棧視為-1,則限制條件為在任意位置前綴和不小于0 。

我們討論這個(gè)問(wèn)題與卡特蘭數(shù)有什么關(guān)系。 為了方便,我們按入棧的先后順序?qū)⒏鱾€(gè)元素由1到n編號(hào)。

假設(shè)最后一個(gè)出棧的數(shù)為k。 則在k入棧之前,比k小的數(shù)一定全部出棧,所以這部分方案數(shù)為h(k-1)。

在k入棧之后,比k大的數(shù)在k入棧之后入棧,在k出棧之前出棧,所以這部分的方案數(shù)為h(n-k)。

這兩部分互不干擾,則方案數(shù)為h(k-1)*h(n-k) 枚舉k,得到的公式就是卡特蘭數(shù)的遞推公式。

                              ——WangKoala

?

大部分Catalan數(shù)的題目都可以抽象為這樣一個(gè)模型,所以深刻理解第一個(gè)遞推式對(duì)快速分析出題目與Catalan有關(guān)很有幫助。

(其實(shí)還是打表最快hhh)

另外,有的題目則根據(jù)Catalan數(shù)的組合意義構(gòu)造模型,比如下面的第一道題。

題目

3907: 網(wǎng)格

Time Limit: 1 Sec??Memory Limit: 256 MB
Submit: 1035??Solved: 367
[Submit][Status][Discuss]

Description

某城市的街道呈網(wǎng)格狀,左下角坐標(biāo)為A(0, 0),右上角坐標(biāo)為B(n, m),其中n >= m。現(xiàn)在從A(0, 0)點(diǎn)出發(fā),只能沿著街道向正右方或者正上方行走,且不能經(jīng)過(guò)圖示中直線左上方的點(diǎn),即任何途徑的點(diǎn)(x, y)都要滿足x >= y,請(qǐng)問(wèn)在這些前提下,到達(dá)B(n, m)有多少種走法。

Input

輸入文件中僅有一行,包含兩個(gè)整數(shù)n和m,表示城市街區(qū)的規(guī)模。

Output

輸出文件中僅有一個(gè)整數(shù)和一個(gè)換行/回車符,表示不同的方案總數(shù)。

Sample Input

6 6

Sample Output

132

HINT

100%的數(shù)據(jù)中,1 <= m <= n <= 5 000

首先考慮n*n的情況。不難發(fā)現(xiàn)此時(shí)答案即為Catalan數(shù)。

如果沒(méi)有線的限制,從$(0,0)-->(n,n)$的總方案數(shù)為$C_{2n}^n$

考慮它的含義:$2n$次操作,其中選$n$次向上走

接下來(lái)需要考慮不合法的情況并減去它。

黃線可以看作合法與不合法情況的分界(一碰就不合法)

我們將矩形沿這條線對(duì)稱過(guò)去,那么碰到黃線后走到$(n,n)$的走法 就可以對(duì)稱為碰到黃線走到$(n-1,n+1)$的走法。

那么顯然不合法方案數(shù)為$C_{2n}^{n-1}$。($2n$次操作中有$n-1$次向右,你把它寫成$C_{2n}^{n+1}$也無(wú)所謂 反正它們相等)

?

至于$n!=m$的情況,以此類推即可。

$ans=C_{n+m}^n-C_{n+m}^{m-1}$?

對(duì)于組合數(shù)計(jì)算,分解質(zhì)因數(shù)約分后用高精乘低精統(tǒng)計(jì)即可。沒(méi)必要高精除。

#include<cstdio> #include<iostream> #include<cstring> #include<vector> using namespace std; int n,m; int pri[1600],tot,vis[10005]; int bu[1600],num1[100005],num2[100005],ans[100005]; void getpri() {for(int i=2;i<=10000;i++){if(!vis[i])pri[++tot]=i;for(int j=1;j<=tot;j++){if(i*pri[j]>10000)break;vis[i*pri[j]]=1;if(i%pri[j]==0)break;}} } void print(int a[]) {for(int i=a[0];i>=1;i--)printf("%d",a[i]);puts(" "); } void div1(int x) {for(int i=1;pri[i]<=x&&x!=1;i++)while(x%pri[i]==0)x/=pri[i],bu[i]++; } void div2(int x) {for(int i=1;pri[i]<=x&&x!=1;i++)while(x%pri[i]==0)x/=pri[i],bu[i]--; } void mult(int x,int a[]) {int k=0;for(int i=1;i<=a[0];i++){int tmp=a[i]*x+k;a[i]=tmp%10;k=tmp/10;}while(k)a[++a[0]]=k%10,k/=10; } void Minus(int a[],int b[]) {int j=1,x=0;while(j<=a[0]||j<=b[0]){if(a[j]<b[j]){a[j]+=10;a[j+1]--;}ans[j]=a[j]-b[j];j++;}int k=j;while(ans[k]==0&&k>1)k--;ans[0]=k; } int main() {getpri();scanf("%d%d",&n,&m); /* div1(n);for(int i=1;i<=10;i++)cout<<bu[i]<<' ';div2(m);for(int i=1;i<=10;i++)cout<<bu[i]<<' ';*/for(int i=n+m;i>=m+1;i--)div1(i);for(int i=n+1;i>=2;i--)div2(i);num1[0]=num1[1]=1;for(int i=1;i<=1600;i++){if(!pri[i])break;if(!bu[i])continue;while(bu[i])mult(pri[i],num1),bu[i]--;}//print(num1);for(int i=0;i<=num1[0];i++)num2[i]=num1[i];mult(n+1,num1);mult(m,num2);//print(num1);print(num2); Minus(num1,num2);print(ans);return 0; } View Code

?

1485: [HNOI2009]有趣的數(shù)列

Time Limit: 10 Sec??Memory Limit: 64 MB
Submit: 2252??Solved: 1205
[Submit][Status][Discuss]

Description

?我們稱一個(gè)長(zhǎng)度為2n的數(shù)列是有趣的,當(dāng)且僅當(dāng)該數(shù)列滿足以下三個(gè)條件:

??? (1)它是從1到2n共2n個(gè)整數(shù)的一個(gè)排列{ai};

??? (2)所有的奇數(shù)項(xiàng)滿足a1<a3<…<a2n-1,所有的偶數(shù)項(xiàng)滿足a2<a4<…<a2n

??? (3)任意相鄰的兩項(xiàng)a2i-1與a2i(1≤i≤n)滿足奇數(shù)項(xiàng)小于偶數(shù)項(xiàng),即:a2i-1<a2i

??? 現(xiàn)在的任務(wù)是:對(duì)于給定的n,請(qǐng)求出有多少個(gè)不同的長(zhǎng)度為2n的有趣的數(shù)列。因?yàn)樽詈蟮拇鸢缚赡芎艽?#xff0c;所以只要求輸出答案 mod P的值。

Input

輸入文件只包含用空格隔開(kāi)的兩個(gè)整數(shù)n和P。輸入數(shù)據(jù)保證,50%的數(shù)據(jù)滿足n≤1000,100%的數(shù)據(jù)滿足n≤1000000且P≤1000000000。

Output

僅含一個(gè)整數(shù),表示不同的長(zhǎng)度為2n的有趣的數(shù)列個(gè)數(shù)mod P的值。

Sample Input

3 10

Sample Output

5


對(duì)應(yīng)的5個(gè)有趣的數(shù)列分別為(1,2,3,4,5,6),(1,2,3,5,4,6),(1,3,2,4,5,6),(1,3,2,5,4,6),(1,4,2,5,3,6)。

?

?

打表找規(guī)律可得答案為Catalan數(shù)。

這題如果強(qiáng)行想的話會(huì)很困難 而且比較浪費(fèi)時(shí)間 所以不如直接打表找規(guī)律。

?還是分解質(zhì)因數(shù)約分,統(tǒng)計(jì)時(shí)取模即可。

#include<cstdio> #include<iostream> #include<cstring> using namespace std; typedef long long ll; ll mod,ans=1; int n,pri[150005],tot,vis[2000005]; int bu[150005],maxi=0,res[2000005]; void getprime() {for(int i=2;i<=2*n;i++){if(!vis[i])pri[++tot]=i,res[i]=tot;for(int j=1;j<=tot;j++){if(i*pri[j]>2*n)break;vis[i*pri[j]]=1;res[i*pri[j]]=j;if(i%pri[j]==0)break;}} } void divi(int x,int val) {while(x!=1)bu[res[x]]+=val,x/=pri[res[x]]; } int main() {scanf("%d%lld",&n,&mod);getprime();for(int i=2*n;i>=n+1;i--)divi(i,1);for(int i=n+1;i>=2;i--)divi(i,-1);for(int i=1;i<=tot;i++)while(bu[i]--)ans=1LL*pri[i]*ans%mod;cout<<ans<<endl;return 0; } View Code

?

2822: [AHOI2012]樹(shù)屋階梯

Time Limit: 1 Sec??Memory Limit: 128 MB
Submit: 1204??Solved: 716
[Submit][Status][Discuss]

Description

暑假期間,小龍報(bào)名了一個(gè)模擬野外生存作戰(zhàn)訓(xùn)練班來(lái)鍛煉體魄,訓(xùn)練的第一個(gè)晚上,教官就給他們出了個(gè)難題。由于地上露營(yíng)濕氣重,必須選擇在高處的樹(shù)屋露營(yíng)。小龍分配的樹(shù)屋建立在一顆高度為N+1尺(N為正整數(shù))的大樹(shù)上,正當(dāng)他發(fā)愁怎么爬上去的時(shí)候,發(fā)現(xiàn)旁邊堆滿了一些空心四方鋼材(如圖1.1),經(jīng)過(guò)觀察和測(cè)量,這些鋼材截面的寬和高大小不一,但都是1尺的整數(shù)倍,教官命令隊(duì)員們每人選取N個(gè)空心鋼材來(lái)搭建一個(gè)總高度為N尺的階梯來(lái)進(jìn)入樹(shù)屋,該階梯每一步臺(tái)階的高度為1尺,寬度也為1尺。如果這些鋼材有各種尺寸,且每種尺寸數(shù)量充足,那么小龍可以有多少種搭建方法?(注:為了避免夜里踏空,鋼材空心的一面絕對(duì)不可以向上。)

?

?? 以樹(shù)屋高度為4尺、階梯高度N=3尺為例,小龍一共有如圖1.2所示的5種

?? 搭 建方法:

??

?

Input

一個(gè)正整數(shù) N(1≤N≤500),表示階梯的高度

Output

一個(gè)正整數(shù),表示搭建方法的個(gè)數(shù)。(注:搭建方法個(gè)數(shù)可能很大。)

Sample Input

3

Sample Output

5

HINT

1? ≤N≤500

?

?

一個(gè)大小為i的階梯,都可以看作由左上角一塊j和右下角一塊i-j-1的階梯,再用矩形填充空缺構(gòu)成。

這樣構(gòu)成的階梯算下來(lái)正好是用i個(gè)鋼材,且方案各不相同。

j在0--i-1取值,可得方案數(shù)的遞推式:

$h_n=h_0*h_{n-1}+h_1*h_{n-2}+...+h_{n-1}*h_0,(n \ge 2)$

這顯然就是Catalan的遞推式。

?

#include<cstdio> #include<iostream> #include<cstring> using namespace std; int n; int pri[1000005],tot,vis[1000005],res[1000005]; int bu[1000005],ans[50005]; void getpri() {for(int i=2;i<=2*n;i++){if(!vis[i])pri[++tot]=i,res[i]=tot;;for(int j=1;j<=tot;j++){if(i*pri[i]>2*n)break;vis[i*pri[j]]=1;res[i*pri[j]]=j;if(i%pri[j]==0)break;}} } void print(int a[]) {for(int i=a[0];i>=1;i--)printf("%d",a[i]);puts(" "); } void divi(int x,int val) {while(x!=1)bu[res[x]]+=val,x/=pri[res[x]]; } void mult(int x,int a[]) {int k=0;for(int i=1;i<=a[0];i++){int tmp=a[i]*x+k;a[i]=tmp%10;k=tmp/10;}while(k)a[++a[0]]=k%10,k/=10; } int main() {scanf("%d",&n);getpri();for(int i=2*n;i>=n+1;i--)divi(i,1);for(int i=n+1;i>=1;i--)divi(i,-1);ans[0]=ans[1]=1;for(int i=1;i<=tot;i++)while(bu[i]--)mult(pri[i],ans);print(ans);return 0; } View Code

?

轉(zhuǎn)載于:https://www.cnblogs.com/Rorschach-XR/p/11222624.html

總結(jié)

以上是生活随笔為你收集整理的[Catalan数三连]网格有趣的数列树屋阶梯的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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