bzoj 1089[SCOI2003]严格n元树 - dp + 高精度

1089: [SCOI2003]严格n元树

Time Limit: 1 Sec  Memory Limit: 162 MB

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
 
 
设 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 }
View Code

 

posted @ 2018-03-24 14:25  大财主  阅读(181)  评论(0编辑  收藏  举报