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;
}
View Code

 

posted @ 2017-02-28 01:16  WDZRMPCBIT  阅读(150)  评论(0编辑  收藏  举报