【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 }