zoukankan      html  css  js  c++  java
  • BZOJ1089: [SCOI2003]严格n元树

    【传送门:BZOJ1089


    简要题意:

      求出深度为d的严格n元树的个数


    题解:

      %%%Hanks_o

      f[i]表示深度小于等于i的严格n元树。 

      那么f[i]怎么用f[i-1]表示呢。 

      对于任意一个深度为i的严格n元树。 

      那么它的根一定有n个儿子。 

      这样我们就可以把它拆成一个根和n棵深度小于等于i-1的n元树了。 

      那么深度小于等于i-1的n元树方案已经求出来了是f[i-1]了呀。 

      那么在利用乘法原理得出f[i]=f[i-1]^n。 

      还没完,还有一棵只有根节点的树,所以f[i]还得+1


    参考代码:

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    using namespace std;
    struct node
    {
        int a[1100],len;
        node()
        {
            len=0;
            memset(a,0,sizeof(a));
        }
    };
    node chengfa(node n1,node n2)
    {
        node no;
        no.len=n1.len+n2.len-1;
        for(int i=1;i<=n1.len;i++) for(int j=1;j<=n2.len;j++) no.a[i+j-1]+=n1.a[i]*n2.a[j];
        for(int i=1;i<=no.len;i++)
        {
            no.a[i+1]+=no.a[i]/10;
            no.a[i]%=10;
        }
        int i=no.len;
        while(no.a[i+1]>0)
        {
            i++;
            no.a[i+1]+=no.a[i]/10;
            no.a[i]%=10;
        }
        no.len=i;
        return no;
    }
    node pow(node a,int b)
    {
        node ans;
        ans.a[1]=1;ans.len=1;
        while(b!=0)
        {
            if(b%2==1) ans=chengfa(ans,a);
            a=chengfa(a,a);
            b/=2;
        }
        return ans;
    }
    node jiafa(node n1)
    {
        node no;
        no=n1;
        no.a[1]+=1;
        for(int i=1;i<=no.len;i++)
        {
            no.a[i+1]+=no.a[i]/10;
            no.a[i]%=10;
        }
        int i=no.len;
        while(no.a[i+1]>0)
        {
            i++;
            no.a[i+1]+=no.a[i]/10;
            no.a[i]%=10;
        }
        no.len=i;
        return no;
    }
    node jianfa(node n1,node n2)
    {
        node no;
        no.len=n1.len;
        for(int i=1;i<=no.len;i++) no.a[i]=n1.a[i]-n2.a[i];
        for(int i=1;i<=no.len;i++)
        {
            if(no.a[i]<0) no.a[i]+=10,no.a[i+1]--;
        }
        int i=no.len;
        while(i>1&&no.a[i]==0) i--;
        no.len=i;
        return no;
    }
    int main()
    {
        int n,d;
        scanf("%d%d",&n,&d);
        if(d==0){printf("1
    ");return 0;}
        node a,b,c;
        a.a[1]=1;a.len=1;
        for(int i=1;i<=d;i++)
        {
            b=pow(a,n);
            if(i<d) a=jiafa(b);
            else c=jiafa(b);
        }
        c=jianfa(c,a);
        for(int i=c.len;i>=1;i--) printf("%d",c.a[i]);
        printf("
    ");
        return 0;
    }

     

  • 相关阅读:
    31天重构学习笔记28. 为布尔方法命名
    .NET 技术社区之我见(中文篇)
    31天重构学习笔记26. 避免双重否定
    31天重构学习笔记25. 引入契约式设计
    31天重构学习笔记20. 提取子类
    31天重构学习笔记18. 使用条件判断代替异常
    31天重构学习笔记19. 提取工厂类
    31天重构学习笔记24. 分解复杂判断
    31天重构学习笔记23. 引入参数对象
    31天重构学习笔记17. 提取父类
  • 原文地址:https://www.cnblogs.com/Never-mind/p/8607324.html
Copyright © 2011-2022 走看看