码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj2822 [AHOI2012]树屋阶梯

时间:2014-12-23 22:29:38      阅读:260      评论:0      收藏:0      [点我收藏+]

标签:

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

 

高精版卡特兰数……直接用模板的速度有点慢

#include<cstdio>
#include<iostream>
#define LL long long
#define mx 1000
using namespace std;
inline LL read()
{
    LL x=0,f=1;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
struct gaojing{
     int len;
     int a[mx+10];
}mult,ans,zero,one;
inline void set0(gaojing &s)
{
    s.len=1;
    for (int i=1;i<=mx+5;i++)s.a[i]=0;
}
inline void inputn(gaojing &a)
{
    set0(a);
    char ch=getchar();
    while (ch<‘0‘||ch>‘9‘)ch=getchar();  
    while (ch>=‘0‘&&ch<=‘9‘)  
    {  
        a.a[a.len++]=ch-‘0‘;
        ch=getchar();
    }
    a.len--;  
    int change[mx+15];
    for (int i=1;i<=a.len;i++)  
      change[i]=a.a[i];  
    for (int i=1;i<=a.len;i++)  
      a.a[i]=change[a.len-i+1];
    while (a.a[a.len]==0)a.len--;
}  
inline void put(gaojing a)
{
    for (int i=a.len;i>=1;i--)printf("%d",a.a[i]);
    printf("\n");
}
inline gaojing operator + (const gaojing &a,const gaojing &b)
{
    gaojing c;set0(c);  
    int maxlen=max(a.len,b.len);      
    for (int i=1;i<=maxlen;i++)      
    {      
        c.a[i]=c.a[i]+a.a[i]+b.a[i];      
        if (c.a[i]>=10)      
        {      
            c.a[i+1]+=c.a[i]/10;    
            c.a[i]%=10;    
        }    
    }      
    c.len=maxlen+4;      
    while (!c.a[c.len]&&c.len>1) c.len--;    
    return c;
}
inline gaojing operator * (const gaojing &a,const gaojing &b)
{
    gaojing c;set0(c);
    for(int i=1;i<=a.len;i++)    
      for (int j=1;j<=b.len;j++)    
        c.a[i+j-1]+=a.a[i]*b.a[j];    
    c.len=a.len+b.len+5;  
    for (int i=1;i<=c.len;i++)    
      {    
        c.a[i+1]+=c.a[i]/10;    
        c.a[i]%=10;    
      }    
    while (!c.a[c.len]&&c.len>1)c.len--;
    return c;
}
inline gaojing operator ^(const gaojing &a,int p)
{
    gaojing ans=one,mult=a;
    while (p)
    {
        if (p&1)ans=ans*mult;
        mult=mult*mult;
        p>>=1;
    }
    return ans;
}
inline void chushihua()
{
    set0(zero); zero.len=1;
    set0(one);one.len=1;one.a[1]=1;
}
int n,len,now;
bool mrk[1010];
int prime[1010],rep[1010],mn[1010];
inline void getprime()
{
    for (int i=2;i<=2*n;i++)
    {
        if (!mrk[i])prime[++len]=i,mn[i]=len;
        for (int j=1;prime[j]*i<=2*n&&j<=len;j++)
        {
            mrk[prime[j]*i]=1;
            mn[prime[j]*i]=j;
            if (i%prime[j]==0)break;
        }
    }
}
inline void calc(int x,int f)
{
    while (x!=1)
    {
        rep[mn[x]]+=f;
        x/=prime[mn[x]];
    }
}
int main()
{
    chushihua();ans=one;mult=one;
    n=read();
    getprime();
    for (int i=n+2;i<=2*n;i++)calc(i,1);
    for (int i=1;i<=n;i++)calc(i,-1);
    for (int i=2;i<=2*n;i++)
    {
        mult=mult+one;
        if (mrk[i])continue;else now++;
        if (rep[now])ans=ans*(mult^rep[now]);
    }
    put(ans);
}

 

bzoj2822 [AHOI2012]树屋阶梯

标签:

原文地址:http://www.cnblogs.com/zhber/p/4181197.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!