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

【BZOJ 2822】[AHOI2012]树屋阶梯 卡特兰数+高精

时间:2017-08-15 10:03:09      阅读:86      评论:0      收藏:0      [点我收藏+]

标签:覆盖   his   logs   for   cst   main   inline   这一   break   

这道题随便弄几个数就发现是卡特兰数然而为什么是呢?

我们发现我们在增加一列时,如果这一个东西(那一列)他就一格,那么就是上一次的方案数,并没有任何改变,他占满了也是,然后他要是占两格呢,就是把原来的切成了n-2,和1,要是就剩一格呢,也是把原来的切成一格和n-2,因为如果一行的某一列被堵了那么这一行的开头的那个台阶表面就覆盖不到那一列.....

这个是从数学角度,由于递推公式的相似性所以是卡特兰数.......

#include <cstdio>
const int STD=10000;
struct Bigint{
  int a[405];
  inline friend Bigint operator * (Bigint A,int B);
  inline void operator *= (int B){
    *this=(*this)*B;
  }
  inline void print(){
    printf("%d",a[a[0]]);
    for(int i=a[0]-1;i>0;i--)
      printf("%04d",a[i]);
  }
}ans;
inline Bigint operator * (Bigint A,int B){
  int x=0;
  for(int i=1;i<=A.a[0];i++){
    A.a[i]=A.a[i]*B+x;
    x=A.a[i]/STD;
    A.a[i]%=STD;
  }
  if(x)A.a[++A.a[0]]=x;
  return A;
}
const int N=1001;
int prime[N],len,size[N],MMin[N];
bool isnot[N];
inline void get_prime(){
  for(int i=2;i<N;i++){
    if(!isnot[i]){
      prime[++len]=i;
      MMin[i]=len;
    }
    for(int j=1;j<=len&&prime[j]*i<N;j++){
      isnot[prime[j]*i]=1;
      MMin[prime[j]*i]=j;
      if(i%prime[j]==0){
        break;
      }
    }
  }
}
inline void get_(int x,int d){
  while(x!=1){
    size[MMin[x]]+=d;
    x/=prime[MMin[x]];
  }
}
int main(){
  get_prime();
  int n;
  ans.a[0]=ans.a[1]=1;
  scanf("%d",&n);
  for(int i=n<<1;i>n+1;i--)
    get_(i,1);
  for(int i=1;i<=n;i++)
    get_(i,-1);
  for(int i=1;i<=len;i++){
    while(size[i])
      ans*=prime[i],size[i]--;
  }
  ans.print();
  return 0;
}

 

【BZOJ 2822】[AHOI2012]树屋阶梯 卡特兰数+高精

标签:覆盖   his   logs   for   cst   main   inline   这一   break   

原文地址:http://www.cnblogs.com/TSHugh/p/7363030.html

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