首页 > 代码库 > bzoj1089 [SCOI2003]严格n元树

bzoj1089 [SCOI2003]严格n元树

1089: [SCOI2003]严格n元树

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 803  Solved: 411
[Submit][Status]

Description

如果一棵树的所有非叶节点都恰好有n个儿子,那么我们称它为严格n元树。如果该树中最底层的节点深度为d(根的深度为0),那么我们称它为一棵深度为d的严格n元树。例如,深度为2的严格2元树有三个,如下图:

给出n, d,编程数出深度为d的n元树数目。

Input

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

Output

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

Sample Input

【样例输入1】
2 2

【样例输入2】
2 3

【样例输入3】
3 5

Sample Output

【样例输出1】
3

【样例输出2】
21

【样例输出2】
58871587162270592645034001
 
这题想了半天也没想出来还是orz了黄巨大才知道怎么做……好烦的dp啊
f[i]=f[i-1]^n+1
ans=f[d]-f[d-1]
要高精的
幸好有个东西叫模板
我说……前面一大堆东西就不用认真看了吧
不过……发现乘方^和加+的优先级有点混乱……只好分开来写
#define mx 300#include<cstdio>#include<iostream>using namespace std;struct gaojing{     int len;     int a[mx+10];}zero,one,f[20];int n,d;inline void set0(gaojing &s)//¸ß¾«ÇåÁã {    s.len=1;    for (int i=1;i<=mx+5;i++)s.a[i]=0;}inline void inputn(gaojing &a)//¸ß¾«ÊäÈë {    set0(a);    char ch=getchar();    while (ch<‘0‘||ch>‘9‘)ch=getchar();      while (ch>=‘0‘&&ch<=‘9‘)      {          a.a[a.len++]=ch-‘0‘;        ch=getchar();    }    a.len--;      int change[mx+15];    for (int i=1;i<=a.len;i++)        change[i]=a.a[i];      for (int i=1;i<=a.len;i++)        a.a[i]=change[a.len-i+1];    while (a.a[a.len]==0)a.len--;}  inline void put(gaojing a)//¸ß¾«Êä³ö {    for (int i=a.len;i>=1;i--)printf("%d",a.a[i]);    printf("\n");}inline bool operator < (const gaojing &a,const gaojing &b)//¸ß¾«< {    if (a.len<b.len)return 1;    if (a.len>b.len)return 0;    for (int i=a.len;i>=1;i--)    {        if (a.a[i]<b.a[i])return 1;        if (a.a[i]>b.a[i])return 0;    }    return 0;}inline bool operator == (const gaojing &a,const gaojing &b)//¸ß¾«>{    if (a.len!=b.len)return 0;    for (int i=a.len;i>=1;i--)    {        if (a.a[i]!=b.a[i])return 0;    }    return 1;}inline gaojing max(const gaojing &a,const gaojing &b)//¸ß¾«max{    if (a<b)return b;    else return a;}inline gaojing min(const gaojing &a,const gaojing &b)//¸ß¾«min{    if (a<b)return a;    else return b;} inline gaojing operator + (const gaojing &a,const gaojing &b)//¸ß¾«+{    gaojing c;set0(c);      int maxlen=max(a.len,b.len);          for (int i=1;i<=maxlen;i++)          {              c.a[i]=c.a[i]+a.a[i]+b.a[i];              if (c.a[i]>=10)              {                  c.a[i+1]+=c.a[i]/10;                c.a[i]%=10;            }        }          c.len=maxlen+4;          while (!c.a[c.len]&&c.len>1) c.len--;        return c;}inline gaojing operator - (const gaojing &a,const gaojing &b)//¸ß¾«-{    gaojing c;set0(c);    gaojing d;d=a;    for (int i=1;i<=b.len;i++)        {          c.a[i]=d.a[i]-b.a[i];          if (c.a[i]<0)          {              c.a[i]+=10;              int now=i+1;              while (!d.a[now])              {                  d.a[now]=9;                  now++;              }              d.a[now]--;          }        }    for (int i=b.len+1;i<=d.len;i++)c.a[i]=d.a[i];      c.len=d.len;      while (c.a[c.len]==0&&c.len>1)c.len--;    return c;}  inline gaojing operator * (const gaojing &a,const gaojing &b)//¸ß¾«*{    gaojing c;set0(c);    for(int i=1;i<=a.len;i++)          for (int j=1;j<=b.len;j++)            c.a[i+j-1]+=a.a[i]*b.a[j];        c.len=a.len+b.len+5;      for (int i=1;i<=c.len;i++)          {            c.a[i+1]+=c.a[i]/10;            c.a[i]%=10;          }        while (!c.a[c.len]&&c.len>1)c.len--;    return c;}inline void div_by_2(gaojing &a){    for (int i=a.len;i>=1;i--)    {        if (a.a[i]&1 && i!=1)a.a[i-1]+=10;        a.a[i]/=2;    }    while (!a.a[a.len]&&a.len>1)a.len--;}inline gaojing operator / (gaojing a,const gaojing &b)//¸ß¾«/{    gaojing l,r,ans;    set0(l);l.len=1;    set0(r);r=a;    set0(ans);ans.len=1;    while (l<r||l==r)    {        gaojing mid=l+r;        div_by_2(mid);        if(mid*b==a)return mid;        if(mid*b<a){ans=mid;l=mid+one;}        if(a<mid*b)r=mid-one;    }    return ans;}inline gaojing operator ^(const gaojing &a,int p)//¸ß¾«^ {	gaojing ans=one,mult=a;	while (p)	{		if (p&1)ans=ans*mult;		mult=mult*mult;		p>>=1;	}	return ans;}inline void chushihua()//³õʼ»¯£¬¶Ô0¡¢1¸ß¾«¶È³£Êý¸³Öµ {    set0(zero); zero.len=1;    set0(one);one.len=1;one.a[1]=1;}int main(){	chushihua();	scanf("%d%d",&n,&d);	f[0]=one;	for (int i=1;i<=d;i++)	{	  f[i]=f[i-1]^n;	  f[i]=f[i]+one;	}	put(f[d]-f[d-1]);}

 

bzoj1089 [SCOI2003]严格n元树