[AHOI2012]树屋阶梯

Posted buringstraw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[AHOI2012]树屋阶梯相关的知识,希望对你有一定的参考价值。

同步:http://buringstraw.win/index.php/archives/17/

题目

技术分享图片

输入格式:

一个正整数N(1<=N<=500),表示阶梯的高度。

输出格式:

一个正整数,表示搭建方法的个数。(注:搭建方法的个数可能很大)

分析

通过人肉打表找规律严格证明发现这是个卡特兰数

然后要求到第500项#(喷)

所以这同时也是个优秀的高精度板子

Code

首先是高精度部分(两个板子的codemix)

struct bigNum{
    private:
        short t[1005];int siz;
        
        
    public:
        bigNum(string a){
            memset(t,0,sizeof(t));
            int len=a.size();
            for(int i=0;i<a.size();++i){
                t[len-i]=a[i];
            }
            siz=len;
        }
        
        bigNum(void){
            memset(t,0,sizeof(t));
            siz=0;
        }
        
        bigNum(long long x){
            memset(t,0,sizeof(t));
            int ws=0;
            while(x){
                ++ws;
                int q=x%10;
                x/=10;
                t[ws]=q;
            }
            siz=ws;
        }
        
        void print(void){
            for(int i=siz;i>=1;--i){
                putchar(t[i]+'0');
            }
            putchar('
');
        }
        
        int size(void){
            return siz;
        }
        
        friend bigNum operator *(bigNum a,long long b){
            bigNum c;
            int len=a.size()+20,g=0;
            for(int i=1;i<=len;++i){
                c.t[i]=a.t[i]*b;
            }
            for(int i=1;i<=len;++i){
                if(c.t[i]>9){
                    c.t[i+1]+=c.t[i]/10;
                    c.t[i]=c.t[i]%10;
                }
            }
            while(len>1&&c.t[len]==0)--len;
            c.siz=len;
            return c;
        }
        
        friend bigNum operator *(long long b,bigNum a){
            return a*b;
        }
        
        friend bigNum operator *(bigNum a,bigNum b){
            bigNum c;
            int len=a.size()+b.size();
            for(int i=1;i<=a.size();++i){
                for(int j=1;j<=b.size();++j){
                    c.t[i+j-1]+=(a.t[i]*b.t[j]);
                }
            }
            
            for(int i=1;i<=len;++i){
                if(c.t[i]>9){
                    c.t[i+1]+=c.t[i]/10;
                    c.t[i]=c.t[i]%10;
                }
            }
            while(len>1 && c.t[len]==0)len--;
            c.siz=len;
            return c;
        }
        
        friend bigNum operator /(bigNum a,long long b){
            bigNum c;
            int k=a.size(),g=0;
            for(int i=k;i>0;--i){
                g=g*10+a.t[i];
                c.t[i]=g/b;
                g%=b;
            }
            while(k>1&&c.t[k]==0)--k;
            c.siz=k;
            return c;
        }
        
        friend bigNum operator /(long long b,bigNum a){
            return a/b;
        }
        
        friend bigNum operator +(bigNum a,bigNum b){
            bigNum c;
            int g=0,k=max(a.size(),b.size());
            for(int i=1;i<=k;i++){
                c.t[i]=a.t[i]+b.t[i]+g;
                g=c.t[i]/10;
                c.t[i]%=10;
            }
            if(g>0){
                c.t[++k]=g;
            }
            c.siz=k;
            return c;
        }
};

然后是卡特兰数部分,

这道题很玄学的地方在于,用递归在我这里会RE,在洛谷和cqyzoj上就不会。。。

用递推会超时。。。

更正:用太过诡异的递推

递归求法(公式2):

bigNum ktl(int x){
    if(x<=0)return 0;
    if(x==1)return 1;
    if(k[x].size())return k[x];
    else return k[x]=(4*x-2)*ktl(x-1)/(x+1);
}

“太过诡异的”递推求法(公式1):

bigNum ktl(int n){
    for(int i=2;i<=n;++i){
        for(int j=0;j<i;++j){
//          printf("%d %d
",i,j);
            k[i]=k[i]+(k[j]*k[i-j-1]);
            //ans.print();
        }
    }
    return k[n];
}

(k的声明):

bigNum k[510]={(bigNum)1,(bigNum)1};

以下为完整代码

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

struct bigNum{
    private:
        short t[1005];int siz;
        
        
    public:
        bigNum(string a){
            memset(t,0,sizeof(t));
            int len=a.size();
            for(int i=0;i<a.size();++i){
                t[len-i]=a[i];
            }
            siz=len;
        }
        
        bigNum(void){
            memset(t,0,sizeof(t));
            siz=0;
        }
        
        bigNum(long long x){
            memset(t,0,sizeof(t));
            int ws=0;
            while(x){
                ++ws;
                int q=x%10;
                x/=10;
                t[ws]=q;
            }
            siz=ws;
        }
        
        void print(void){
            for(int i=siz;i>=1;--i){
                putchar(t[i]+'0');
            }
            putchar('
');
        }
        
        int size(void){
            return siz;
        }
        
        friend bigNum operator *(bigNum a,long long b){
            bigNum c;
            int len=a.size()+20,g=0;
            for(int i=1;i<=len;++i){
                c.t[i]=a.t[i]*b;
            }
            for(int i=1;i<=len;++i){
                if(c.t[i]>9){
                    c.t[i+1]+=c.t[i]/10;
                    c.t[i]=c.t[i]%10;
                }
            }
            while(len>1&&c.t[len]==0)--len;
            c.siz=len;
            return c;
        }
        
        friend bigNum operator *(long long b,bigNum a){
            return a*b;
        }
        
        friend bigNum operator *(bigNum a,bigNum b){
            bigNum c;
            int len=a.size()+b.size();
            for(int i=1;i<=a.size();++i){
                for(int j=1;j<=b.size();++j){
                    c.t[i+j-1]+=(a.t[i]*b.t[j]);
                }
            }
            
            for(int i=1;i<=len;++i){
                if(c.t[i]>9){
                    c.t[i+1]+=c.t[i]/10;
                    c.t[i]=c.t[i]%10;
                }
            }
            while(len>1 && c.t[len]==0)len--;
            c.siz=len;
            return c;
        }
        
        friend bigNum operator /(bigNum a,long long b){
            bigNum c;
            int k=a.size(),g=0;
            for(int i=k;i>0;--i){
                g=g*10+a.t[i];
                c.t[i]=g/b;
                g%=b;
            }
            while(k>1&&c.t[k]==0)--k;
            c.siz=k;
            return c;
        }
        
        friend bigNum operator /(long long b,bigNum a){
            return a/b;
        }
        
        friend bigNum operator +(bigNum a,bigNum b){
            bigNum c;
            int g=0,k=max(a.size(),b.size());
            for(int i=1;i<=k;i++){
                c.t[i]=a.t[i]+b.t[i]+g;
                g=c.t[i]/10;
                c.t[i]%=10;
            }
            if(g>0){
                c.t[++k]=g;
            }
            c.siz=k;
            return c;
        }
};

bigNum k[510]={(bigNum)1,(bigNum)1};

/*bigNum ktl(int x){
    if(x<=0)return 0;
    if(x==1)return 1;
    if(k[x].size())return k[x];
    else return k[x]=(4*x-2)*ktl(x-1)/(x+1);
}*/

bigNum ktl(int n){
    for(int i=2;i<=n;++i){
        k[i]=(4*i-2)*k[i-1]/(i+1);
    }
    return k[n];
}

int main(void){
    int n;
    cin>>n;
    ktl(n).print();
//  bigNum a(123),b(45);
//  (a*b).print();
    return 0;
}

以上是关于[AHOI2012]树屋阶梯的主要内容,如果未能解决你的问题,请参考以下文章

[AHOI2012]树屋阶梯 题解(卡特兰数)

[AHOI2012] 树屋阶梯

bzoj2822[AHOI2012]树屋阶梯(卡特兰数)

洛谷P2532 [AHOI2012]树屋阶梯(Catalan数)

[AHOI2012]树屋阶梯

[AHOI2012]树屋阶梯