[BZOJ]1089: [SCOI2003]严格n元树 DP+高精度

来源:互联网 发布:无心法师白琉璃知乎 编辑:程序博客网 时间:2024/05/29 10:24

Description

  如果一棵树的所有非叶节点都恰好有n个儿子,那么我们称它为严格n元树。如果该树中最底层的节点深度为d(根的深度为0),那么我们称它为一棵深度为d的严格n元树。给出n, d,编程数出深度为d的n元树数目。

Input

  仅包含两个整数n, d( 0 < n < = 32, 0 < = d < = 16)

Output

  仅包含一个数,即深度为d的n元树的数目。

题解:

f[i]表示深度小于等于in元树有多少。可以发现,对于一个n元树,都是由根节点+n个子树组成的,而每个子树又是一个深度小于等于i1n元树,再加上一种只有一个根节点的情况,所以有转移方程f[i]=f[i1]n+1。需要用高精度,发博客主要为了存一存新的高精度模版。(以前都是不用重载运算符的)。

代码:

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int M=10000;struct node{    int v[10010],l;}f[20];node operator * (node a,node b){    node c;    c.l=a.l+b.l;    for(int i=1;i<=c.l;i++)c.v[i]=0;    for(int i=1;i<=a.l;i++)    for(int j=1;j<=b.l;j++)    c.v[i+j-1]+=a.v[i]*b.v[j];    for(int i=1;i<=c.l;i++)    if(c.v[i]>=M)    {        if(i==c.l)c.v[++c.l]=c.v[i]/M;        else c.v[i+1]+=c.v[i]/M;        c.v[i]%=M;    }    while(c.l>1&&!c.v[c.l])c.l--;    return c;}node operator + (node a,int b){    node c=a;    c.v[1]+=b;    for(int i=1;i<=c.l;i++)    if(c.v[i]>=M)    {        if(i==c.l)c.v[++c.l]=c.v[i]/M;        else c.v[i+1]+=c.v[i]/M;        c.v[i]%=M;    }    return c;}node operator - (node a,node b){    node c;    c.l=max(a.l,b.l);    for(int i=1;i<=c.l;i++)c.v[i]=0;    for(int i=1;i<=c.l;i++)    {        c.v[i]+=a.v[i]-b.v[i];        if(c.v[i]<0)        {            c.v[i]+=M;            c.v[i+1]--;            if(i+1==c.l&&c.v[i+1]==0)c.l--;        }    }    while(c.l>1&&!c.v[c.l])c.l--;    return c;}node p(node x,int y){    if(y==1)return x;    node t=p(x,y>>1),ans=t*t;    if(y&1)ans=ans*x;    return ans;}int main(){    int n,d;    scanf("%d%d",&n,&d);    if(d==0){puts("1");return 0;}    f[0].v[1]=1;f[0].l=1;    for(int i=1;i<=d;i++)f[i]=p(f[i-1],n)+1;    node ans=f[d]-f[d-1];    printf("%d",ans.v[ans.l]);    for(int i=ans.l-1;i;i--)    printf("%04d",ans.v[i]);}
阅读全文
2 0