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

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

我们发现我们在增加一列时,如果这一个东西(那一列)他就一格,那么就是上一次的方案数,并没有任何改变,他占满了也是,然后他要是占两格呢,就是把原来的切成了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;
}
原文地址:https://www.cnblogs.com/TSHugh/p/7363030.html