BZOJ2822 AHOI2012 树屋阶梯 Catalan数+高精度
题意:(没图不好说……)
题解:
自己计算出前三种方案后,发现和Catalan数的前三项契合,因此就当Catalan数写了,最后竟然过了- -。(结论就是多背几个数列还是有好处的)
AC之后看了题解,才知道具体是怎么证的。
通过包含左下角那个方块的方块,可以将楼梯划成两个部分。也就是说,第i层楼梯和左下角的矩形会把整个楼梯划分成i-1层的楼梯和n-i层的楼梯,因此f[i]=sum(f[j-1]*f[i-j])符合Catalan数的递推式,然后用一阶的递推式算就好。
#include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; const int MAXL=6000+2; const int BASE=10000; struct BIGNUM{ int num[MAXL],len; BIGNUM(int zero=0){ num[len=1]=zero;} BIGNUM operator +(const BIGNUM &a)const{ int carry=0; BIGNUM tmp; tmp.len=max(len,a.len); for(int i=1;i<=tmp.len;i++){ tmp.num[i]=carry+num[i]+a.num[i]; carry=tmp.num[i]/BASE,tmp.num[i]%=BASE; } if(carry) tmp.num[++tmp.len]=carry; return tmp; } BIGNUM operator *(int a)const{ int carry=0; BIGNUM tmp; tmp.len=len; for(int i=1;i<=tmp.len;i++){ tmp.num[i]=carry+a*num[i]; carry=tmp.num[i]/BASE,tmp.num[i]%=BASE; } while(carry) tmp.num[++tmp.len]=carry%BASE,carry/=BASE; return tmp; } BIGNUM operator /(int a)const{ int borrow=0; BIGNUM tmp; tmp.len=len; for(int i=len;i;i--){ tmp.num[i]=(borrow+num[i])/a; borrow=(borrow+num[i])%a*BASE; } while(!tmp.num[tmp.len]) tmp.len--; return tmp; } }ans(1); int n; int main(){ cin >> n; for(int i=2;i<=n;i++) ans=ans*(4*i-2)/(i+1); cout << ans.num[ans.len]; for(int i=ans.len-1;i;i--) printf("%04d",ans.num[i]); cout << endl; return 0; }