1. 程式人生 > >[AHOI2012]樹屋階梯

[AHOI2012]樹屋階梯

ostream www. int() tro class ++ 描述 搭建 i++

題目描述

技術分享

技術分享

輸入輸出格式

輸入格式:

一個正整數N(1<=N<=500),表示階梯的高度。

輸出格式:

一個正整數,表示搭建方法的個數。(註:搭建方法的個數可能很大)

輸入輸出樣例

輸入樣例#1: 復制
3
輸出樣例#1: 復制
5

說明

40%的數據:1<=N<=20

80%的數據:1<=N<=300

100%的數據:1<=N<=500

轉載自Navi_Gayson:http://www.cnblogs.com/NaVi-Awson/p/7748308.html

我們令$C_n$表示用$n$個長方形拼成$size$為$n$的三角梯形的方案數。

如題中的圖,我們枚舉最左下角的點屬於哪個長方形。顯然有$n$種可能,每種方法又把剩下的部分分成兩個三角梯形($size$可能為$0$)。

顯然我們得到

$$Catalan_n = \sum _{i = 0} ^{n-1} Catalan_i * Catalan_{n-1-i}$$

其實就是$Catalan$的遞推式,我們用通項公式求$Catalan_n$即可。

Catalann=C(n,2n)/(n+1)

學習一下Catalan,順便復習一下重載運算符

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4
#include<algorithm> 5 #include<cmath> 6 using namespace std; 7 int n; 8 struct Big_num 9 { 10 int a[10005],len; 11 Big_num(){} 12 Big_num &operator *= (const int &b) 13 {int i; 14 for (i=1;i<=len;i++) 15 a[i]*=b; 16 for (i=1;i<=len;i++)
17 a[i+1]+=a[i]/10,a[i]%=10; 18 while (a[len+1]) 19 { 20 len++; 21 a[len+1]+=a[len]/10; 22 a[len]%=10; 23 } 24 } 25 Big_num &operator /=(const int b) 26 { 27 int now=0,i; 28 Big_num ans; 29 for (i=len;i>=1;i--) 30 { 31 now=now*10+a[i]; 32 if (now>=b) ans.a[i]=now/b,now%=b; 33 else ans.a[i]=0; 34 } 35 while (ans.a[len]==0) 36 len--; 37 for (i=1;i<=len;i++) a[i]=ans.a[i]; 38 } 39 void print() 40 {int i; 41 for (i=len;i>=1;i--) 42 printf("%d",a[i]); 43 cout<<endl; 44 } 45 }Ans; 46 int main() 47 {int i; 48 cin>>n; 49 Ans.len=Ans.a[1]=1; 50 for (i=n+2;i<=2*n;i++) Ans*=i; 51 for (i=2;i<=n;i++) 52 Ans/=i; 53 Ans.print(); 54 }

[AHOI2012]樹屋階梯