[AHOI2012]树屋阶梯
做题时间:2022.7.5
\(【题目描述】\)
给定一个高为 \(N(1\leq N\leq 500)\) 的阶梯型(如图是高度为4的阶梯型)

将其划分为 \(N\) 个矩形(划分线必须与网格线重合),问方案数。
\(【输入格式】\)
一个整数 \(N\)
\(【输出格式】\)
一个整数表示方案数
\(【考点】\)
卡特兰数列,高精度
\(【做法】\)
枚举前3项可以发现是\(1,2,5\) ,很有可能是卡特兰数列。原题是几何类问题,可以考虑类比凸 \(n+2\) 边形问题(catalan的经典问题)。
由于右上角有 \(N\) 个拐角,题目又要求划分为 \(N\) 个矩形,因此每一个矩形覆盖住一个拐角,也就是说没有矩形放在阶梯型中间而不与拐角接触。
考虑左下角的一格,设覆盖住这一格的矩形大小为 \(a\times b\) ,这个大阶梯型就被分成了左上角一个高为 \(N-a\) 的阶梯型,中间一个 \(a\times b\) 的矩形,右下角一个高为 \(N-b\) 的阶梯型,很想凸 \(n+2\) 边形问题,递归求解即可。
注意要写压位高精
\(【代码】\)
#include<cstdio>
#include<iomanip>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=1e3+50,BIT=1000000000;
inline int Max(int a,int b){return a>b?a:b;}
struct BigNum{
ll num[N];
int len;
BigNum(){
memset(num,0,sizeof(num));
len=0;
}
BigNum operator +(const BigNum b){
BigNum c;
c.len=Max(len,b.len);
for(int i=1;i<=c.len;i++){
c.num[i]+=num[i]+b.num[i];
if(c.num[i]>=BIT) c.num[i]-=BIT,c.num[i+1]++;
}
if(c.num[c.len+1]) c.len++;
return c;
}
BigNum operator *(const BigNum b){
BigNum c;
c.len=len+b.len;
ll x=0;
for(int i=1;i<=len;i++){
for(int j=1;j<=b.len;j++){
c.num[i+j-1]+=num[i]*b.num[j]+x;
x=c.num[i+j-1]/BIT,c.num[i+j-1]%=BIT;
}
if(x) c.num[b.len+i]=x;
x=0;
}
while(!c.num[c.len]&&c.len>1) c.len--;
return c;
}
}H[N];
int n;
void Print(BigNum ans)
{
for(int i=ans.len;i>=1;i--){//压位高精输出
if(i==ans.len) printf("%lld",ans.num[i]);
else printf("%09lld",ans.num[i]);
}
printf("\n");
}
int main()
{
scanf("%d",&n);
H[0].len=1,H[0].num[1]=1;
H[1].len=1,H[1].num[1]=1;
for(int i=2;i<=n;i++){//卡特兰数递推公式
for(int j=0;j<=i-1;j++) H[i]=H[i]+(H[j]*H[i-j-1]);
}
Print(H[n]);
return 0;
}

浙公网安备 33010602011771号