首页 > 代码库 > 【noi 2.6_9280】&【bzoj 1089】严格n元树(DP+重载运算符)

【noi 2.6_9280】&【bzoj 1089】严格n元树(DP+重载运算符)

题意:定义一棵树的所有非叶节点都恰好有n个儿子为严格n元树。问深度为d的严格n元树数目。

解法:f[i]表示深度为<=i的严格n元树数目。f[i]-f[i-1]表示深度为i的严格n元树数目。f[i]=f[i-1]^n+1。d层的严格n元树可分解为1个根节点和n棵d-1层的严格n元树。利用乘法原理,再加上子树为空的一种情况。

P.S.同样要注意递推的思想!                           

 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 using namespace std; 6  7 struct node 8 { 9     int l;10     int s[210];11     node() {l=0;memset(s,0,sizeof(s));}12 }f[20];13 14 int mmax(int x,int y) {return x>y?x:y;}15 node operator+(node x,int y)16 {17     int t=1;18     x.s[t]+=y;19     while (x.s[t]>9) x.s[t+1]+=x.s[t]/10,x.s[t]%=10,t++;20     return x;21 }22 node operator-(node x,node y)23 {24     node z;25     z.l=mmax(x.l,y.l);26     for (int i=1;i<=z.l;i++)27     {28       if (x.s[i]<y.s[i]) x.s[i]+=10,x.s[i+1]--;29       z.s[i]+=x.s[i]-y.s[i];30       if (z.s[i]>9) z.s[i+1]+=z.s[i]/10,z.s[i]%=10;31     }32     while (!z.s[z.l]) z.l--;33     return z;34 }35 node operator*(node x,node y)36 {37     node z;38     z.l=x.l+y.l-1;39     for (int i=1;i<=x.l;i++)40      for (int j=1;j<=y.l;j++)//不同于+!41      {42       z.s[i+j-1]+=x.s[i]*y.s[j];43       if (z.s[i+j-1]>9) z.s[i+j]+=z.s[i+j-1]/10,z.s[i+j-1]%=10;44      }45     while (z.s[z.l+1]) z.l++;46     return z;47 }48 node operator^(node x,int y)49 {50     node z=x,u=x;51     y--;52     while (y>0)53     {54       if (y%2) z=z*u;55       u=u*u;//同底数幂相乘为指数的加法56       y/=2;57     }58     return z;59 }60 void print(node x)61 {62     for (int i=x.l;i>=1;i--)//converse!!63       printf("%d",x.s[i]);64     printf("\n");65 }66 int main()67 {68     int n,d;69     scanf("%d%d",&n,&d);70     f[0].l=1,f[0].s[1]=1;71     f[1].l=1,f[1].s[1]=2;72     for (int i=2;i<=d;i++)73       f[i]=(f[i-1]^n)+1;74     print(f[d]-f[d-1]);//75     return 0;76 }

 

【noi 2.6_9280】&【bzoj 1089】严格n元树(DP+重载运算符)