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

    [AHOI2012]树屋阶梯

    要构成一个(n imes n)的阶梯形图形,如图,但你只能用n个长方形构成这个图形,询问其方案数,(1<=N<=500)

    pic1

    其实注意到题目很简单,而且还是很奇怪的组合计数,在加上样例(1,2,5,14),你就能猜到这是一个catalan数列。

    但还是按照正规的思路来,组合计数问题,显然无法推出通项公式,于是考虑递推方程,设(f[n])表示长度为n的阶梯形图形划分方案数,问题在于接下无法根据策略转移,考虑划分,尝试把它划分成两个完整的阶梯,于是我们完全可以利用一个端点在最左下角的,一个端点在阶梯上的点的正方形划分问题,于是有

    (f[n]=f[1]f[n-1]+f[2]f[n-2]+...f[n-1][1])

    边界:(f[1]=1)

    于是很快反应过来,这就是catalan数的递推公式,于是不用递推方程,它只是负责证明,接下来套用其公式,利用高精阶乘分解质因数的方法即可。

    参考代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define il inline
    #define ri register
    using namespace std;
    struct lll{
        short num[5000];
        il lll(){num[0]=1;}
        il void clear(){
            memset(num,0,sizeof(num)),num[0]=1;
        }
        il void read(){
            string s;cin>>s,num[0]=s.size();
            for(ri int i(1);i<=num[0];++i)
                num[i]=s[num[0]-i]-48;
        }
        il void print(){
            for(ri int i(num[0]);i;--i)
                putchar(num[i]+48);
        }
        il void operator=(int x){
            num[0]&=0;
            while(x)num[++num[0]]=x%10,x/=10;
        }
        il lll operator*(lll x){
            lll y;y.clear();
            for(ri int i(1),j,k;i<=num[0];++i){
                k&=0;
                for(j=1;j<=x.num[0];++j)
                    y.num[i+j-1]+=num[i]*x.num[j]+k,
                        k=y.num[i+j-1]/10,y.num[i+j-1]%=10;
                y.num[i+x.num[0]]+=k;
            }y.num[0]=num[0]+x.num[0];
            while(!y.num[y.num[0]]&&y.num[0]>1)--y.num[0];
            return y;
        }template<class free>
        il lll operator^(free y){
            lll x(*this),ans;ans=1;
            while(y){
                if(y&1)ans=ans*x;
                x=x*x,y>>=1;
            }return ans;
        }
    }xdk[201];
    bool check[1001];
    int prime[201],pt;
    il void cat(int),sieve(int);
    int main(){
        int n;scanf("%d",&n);
        sieve(n<<1),cat(n);
        return 0;
    }
    il void sieve(int n){
        check[1]|=true;
        for(ri int i(2),j;i<=n;++i){
            if(!check[i])prime[++pt]=i,xdk[pt]=i;
            for(j=1;j<=pt&&i*prime[j]<=n;++j){
                check[i*prime[j]]|=true;
                if(!(i%prime[j]))break;
            }
        }
    }
    il void cat(int n){
        lll ans;ans=1;
        int n2(n<<1),i,j,wch(n+1),tr;
        for(i=1;i<=pt;++i){
            tr&=0;
            for(j=n2;j;j/=prime[i])tr+=j/prime[i];
            for(j=n;j;j/=prime[i])tr-=j/prime[i]<<1;
            while(!(wch%prime[i]))wch/=prime[i],--tr;
            ans=ans*(xdk[i]^tr);
        }ans.print();
    }
    
    
  • 相关阅读:
    Windows Azure Cloud Service (14) 使用Windows Azure诊断收集日志记录数据
    Windows Azure Cloud Service (13) 用Visual Studio 2010 将应用程序部署到Windows Azure平台
    Windows Azure Cloud Service (15) 多个VM Instance场景下如何处理ASP.NET Session
    Windows Azure Storage (5) Windows Azure Drive
    Windows Azure Storage (7) 使用工具管理Windows Azure Storage
    SQL Azure(二) SQL Azure vs SQL Server
    webbrowser的自动提交
    提取视频的背景声音的软件
    Listview列排序的bug原因
    两个奇怪的问题
  • 原文地址:https://www.cnblogs.com/a1b3c7d9/p/10804920.html
Copyright © 2011-2022 走看看