zoukankan      html  css  js  c++  java
  • BZOJ2822: [AHOI2012]树屋阶梯

    BZOJ2822: [AHOI2012]树屋阶梯

    Description

    暑假期间,小龙报名了一个模拟野外生存作战训练班来锻炼体魄,训练的第一个晚上,教官就给他们出了个难题。
    由于地上露营湿气重,必须选择在高处的树屋露营。
    小龙分配的树屋建立在一颗高度为N+1尺(N为正整数)的大树上,正当他发愁怎么爬上去的时候,发现旁边堆满了一些空心四方钢材(如图1.1),经过观察和测量,这些钢材截面的宽和高大小不一,但都是1尺的整数倍,教官命令队员们每人选取N个空心钢材来搭建一个总高度为N尺的阶梯来进入树屋,该阶梯每一步台阶的高度为1尺,宽度也为1尺。
    如果这些钢材有各种尺寸,且每种尺寸数量充足,那么小龙可以有多少种搭建方法?
    (注:为了避免夜里踏空,钢材空心的一面绝对不可以向上。)

       以树屋高度为4尺、阶梯高度N=3尺为例,小龙一共有如图1.2所示的5种搭建方法:

       

    Input

    一个正整数 N(1N500),表示阶梯的高度

    Output

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

    Sample Input

    3

    Sample Output

    5

    HINT

    1N500

    题解Here!

    卡特兰数+高精乘+gcd

    为什么是 卡特兰数 ?

    玄学:

    n=1 , ans=1 ; n=2 , ans=2 ; n=3 , ans=5 ;于是想到了卡特兰数。。。

    正解:

    我们发现对于任何大小为 i 的树屋阶梯,都可以由左上角放一块大小为 j 的以及右下角放一块大小为 ( i - j - 1 ) 的树屋阶梯,再在空缺的地方由单个大块的矩形填充即可构成,这个构成的树屋阶梯一共有 ( j ) + ( i - j - 1 ) 个钢材,正好是 i 个。

    因为 j 可以在 0 到 i - 1 取且可以证明每一个构成的树屋阶梯一定各不相同,所以我们可以得到树屋阶梯方案与大小关系的递推式:

    f[i]=f[i-1]*f[0]+f[i-2]*f[1]+...+f[0]*f[i-1];
    

    同时,我们规定:

    f[0]=f[1]=1;

    哦,这不就是卡特兰数的递推式吗?于是我们就可以安心将这道题当作卡特兰数的模板题食用了。

    公式:

    cal(n)=C(n,2n)/(n+1)=(2n)!/(n!×(n+1)!)=(n+2)(n+3)(n+4)...(2n)/(1×2×3×...×n)
    

    将分子分母全部分别存入两个数组,一个一个求出 gcd,再化简,最后用高乘单求出结果,输出即可。。。

    附代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #define MAXN 510
    using namespace std;
    int n,a[MAXN],b[MAXN],ans[MAXN*10];
    int gcd(int x,int y){
        if(!y)return x;
        return gcd(y,x%y);
    }
    void mul(int x){
        int c=0;
        for(int i=1;i<=ans[0];i++){
            ans[i]*=x;ans[i]+=c;
            c=ans[i]/10;
            ans[i]%=10;
        }
        while(c){
            ans[++ans[0]]=c%10;
            c/=10;
        }
    }
    int main(){
        cin>>n;
        for(int i=2;i<=n;i++){a[i-1]=n+i;b[i-1]=i;}
        for(int i=1;i<n;i++)
        for(int j=1;j<n;j++){
            if(b[j]==1)continue;
            int g=gcd(a[i],b[j]);
            if(g!=1){a[i]/=g;b[j]/=g;}
            if(a[i]==1)break;
        }
        ans[0]=ans[1]=1;
        for(int i=1;i<n;i++){
            if(a[i]==1)continue;
            mul(a[i]);
        }
        for(int i=ans[0];i>=1;i--)printf("%d",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    Open source cryptocurrency exchange
    Salted Password Hashing
    95. Unique Binary Search Trees II
    714. Best Time to Buy and Sell Stock with Transaction Fee
    680. Valid Palindrome II
    Java compiler level does not match the version of the installed Java project facet.
    eclipse自动编译
    Exception in thread "main" java.lang.StackOverflowError(栈溢出)
    博客背景美化——动态雪花飘落
    java九九乘法表
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9048799.html
Copyright © 2011-2022 走看看