zoukankan      html  css  js  c++  java
  • 【BZOJ 2822】2822: [AHOI2012]树屋阶梯(卡特兰数+高精度)

    2822: [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

    1  ≤N500

    Source

    【分析】

      这个卡特兰数的模型很经典吧,我之前的总结里面也应该有的。

      看图显然卡特兰数。高精度。用分解质因数的方法,就是高精乘低精而已。

      然后简单说说为什么是卡特兰数?

      

      看下面那个很丑的图,编号的那些格子是角落的,很明显是两两不能处于同一块木板的。

      就是说这7个格子正好处在7块不同的木板上。(你刚好要用7块木板)

      然后?的一定在某一块模板上。比如跟4一个木板,第二个图,就变成两个3阶梯的子问题。

      如果跟6一个板,就变成一个5阶梯和一个1阶梯的子问题。
      就是f[n]=f[0]*f[n-1]+f[1]*f[n-2]+...f[n-1]*f[0]

      这个是卡特兰数的一种定义。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 using namespace std;
     7 #define Maxn 510
     8 #define Maxm 2010
     9 
    10 int num[Maxn*2];
    11 
    12 void add(int x,int c)
    13 {
    14     for(int i=2;i*i<=x;i++) if(x%i==0)
    15     {
    16         while(x%i==0) num[i]+=c,x/=i;
    17     }
    18     if(x!=1) num[x]+=c;
    19 }
    20 
    21 int ans[Maxm],ll;
    22 
    23 void mul(int x)
    24 {
    25     for(int i=1;i<=ll;i++) ans[i]*=x;
    26     for(int i=1;i<=ll;i++)
    27     {
    28         ans[i+1]+=ans[i]/10;
    29         ans[i]%=10;
    30     }
    31     while(ans[ll+1]!=0)
    32     {
    33         ans[ll+2]+=ans[ll+1]/10;
    34         ans[ll+1]%=10;
    35         ll++;
    36     }
    37 }
    38 
    39 int main()
    40 {
    41     int n;
    42     scanf("%d",&n);
    43     memset(num,0,sizeof(num));
    44     for(int i=n+1;i<=2*n;i++) add(i,1);
    45     for(int i=1;i<=n+1;i++) add(i,-1);
    46     memset(ans,0,sizeof(ans));
    47     ans[1]=1;ll=1;
    48     for(int i=1;i<=2*n;i++) if(num[i])
    49     {
    50         while(num[i]>0) mul(i),num[i]--;
    51     }
    52     for(int i=ll;i>=1;i--) printf("%d",ans[i]);printf("
    ");
    53     return 0;
    54 }
    View Code

    2017-03-23 16:11:36

  • 相关阅读:
    关于java集合框架(二):List
    仪式感
    java的foreach(增强for循环)
    关于Java集合框架(一):概述与Set
    重新开始
    简单fork循环分析
    fork,写时复制(copy-on-write),vfork
    树莓派换源
    Windows下TexLive2018环境配置及检测
    Linux下高精度时间
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6605700.html
Copyright © 2011-2022 走看看