bzoj 1089[SCOI2003]严格n元树 - dp + 高精度
1089: [SCOI2003]严格n元树
Time Limit: 1 Sec Memory Limit: 162 MBDescription
如果一棵树的所有非叶节点都恰好有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
2 2
【样例输入2】
2 3
【样例输入3】
3 5
Sample Output
【样例输出1】
3
【样例输出2】
21
【样例输出2】
58871587162270592645034001
3
【样例输出2】
21
【样例输出2】
58871587162270592645034001
设 dp[i] 表示 深度 <= i 的严格n元树的个数
则 dp[i] = dp[i - 1] ^ n + 1
相当于在最上面加一个根节点, n个儿子可以随便填,还要 + 1是因为有 没有儿子的情况
顺便练一下高精度
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #define LL long long 6 7 using namespace std; 8 9 int n, d; 10 11 inline LL read() 12 { 13 LL x = 0, w = 1; char ch = 0; 14 while(ch < '0' || ch > '9') { 15 if(ch == '-') { 16 w = -1; 17 } 18 ch = getchar(); 19 } 20 while(ch >= '0' && ch <= '9') { 21 x = x * 10 + ch - '0'; 22 ch = getchar(); 23 } 24 return x * w; 25 } 26 27 struct bignum { 28 int len; 29 int a[1000]; 30 void init() 31 { 32 memset(a, 0, sizeof a); 33 } 34 } temp, dp[400], one, t, ans; 35 36 bignum operator +(bignum a, bignum b) 37 { 38 int len = max(a.len, b.len); 39 temp.init(); 40 for(int i = 1; i <= len; i++) { 41 temp.a[i] = a.a[i] + b.a[i]; 42 } 43 for(int i = 1; i <= len; i++) { 44 temp.a[i + 1] += temp.a[i] / 10; 45 temp.a[i] = temp.a[i] % 10; 46 } 47 temp.len = len; 48 if(temp.a[temp.len + 1] != 0) { 49 temp.len++; 50 } 51 return temp; 52 } 53 54 bignum operator *(bignum a, bignum b) 55 { 56 int len = a.len + b.len + 1; 57 temp.init(); 58 for(int i = 1; i <= a.len; i++) { 59 for(int j = 1; j <= b.len; j++) { 60 temp.a[i + j - 1] += a.a[i] * b.a[j]; 61 } 62 } 63 for(int i = 1; i <= len; i++) { 64 temp.a[i + 1] += temp.a[i] / 10; 65 temp.a[i] = temp.a[i] % 10; 66 } 67 temp.len = len; 68 while(temp.a[temp.len] == 0) { 69 temp.len--; 70 } 71 return temp; 72 } 73 74 bignum operator -(bignum a, bignum b) 75 { 76 int len = a.len; 77 temp.init(); 78 for(int i = 1; i <= a.len; i++) { 79 if(a.a[i] < b.a[i]) { 80 a.a[i] += 10; 81 a.a[i + 1]--; 82 } 83 temp.a[i] = a.a[i] - b.a[i]; 84 } 85 while(temp.a[temp.len] == 0) { 86 temp.len--; 87 } 88 return temp; 89 } 90 91 void print(bignum a) 92 { 93 for(int i = a.len; i >= 1; i--) { 94 printf("%d", a.a[i]); 95 } 96 } 97 98 bignum fast(bignum a, int k) 99 { 100 bignum cnt = a; 101 bignum res = one; 102 while(k) { 103 if(k % 2 == 1) { 104 res = cnt * res; 105 k--; 106 } else { 107 cnt = cnt * cnt; 108 k = k / 2; 109 } 110 } 111 return res; 112 } 113 int main() 114 { 115 n = read(), d = read(); 116 dp[0].len = 1, dp[0].a[1] = 1; 117 one.len = 1, one.a[1] = 1; 118 for(int i = 1; i <= d; i++) { 119 dp[i] = fast(dp[i - 1], n) + one; 120 } 121 if(d == 0) { 122 printf("1\n"); 123 return 0; 124 } 125 ans = dp[d] - dp[d - 1]; 126 print(ans); 127 return 0; 128 }