BZOJ1089:[SCOI2003]严格n元树(DP,高精度)

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

Solution

DP方程好想= =
$f[i]$表示深度不超过$i$的树的种数
$f[i]=f[i-1]^n+1$。加1是因为儿子可能为空。
最后答案为$f[d]-f[d-1]$
需要高精度……不过懒得写了直接套了个板子QAQ

Code

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #define N (509)
  5 using namespace std;
  6 
  7 struct bign
  8 {
  9     int len, s[N];
 10     bign ()
 11     {
 12         memset(s, 0, sizeof(s));
 13         len = 1;
 14     }
 15     bign (int num) { *this = num; }
 16     bign (const char *num) { *this = num; }
 17     bign operator = (const int num)
 18     {
 19         char s[N];
 20         sprintf(s, "%d", num);
 21         *this = s;
 22         return *this;
 23     }
 24     bign operator = (const char *num)
 25     {
 26         for(int i = 0; num[i] == '0'; num++) ;  //去前导0
 27         len = strlen(num);
 28         for(int i = 0; i < len; i++) s[i] = num[len-i-1] - '0';
 29         return *this;
 30     }
 31     bign operator + (const bign &b) const //+
 32     {
 33         bign c;
 34         c.len = 0;
 35         for(int i = 0, g = 0; g || i < max(len, b.len); i++)
 36         {
 37             int x = g;
 38             if(i < len) x += s[i];
 39             if(i < b.len) x += b.s[i];
 40             c.s[c.len++] = x % 10;
 41             g = x / 10;
 42         }
 43         return c;
 44     }
 45     bign operator += (const bign &b)
 46     {
 47         *this = *this + b;
 48         return *this;
 49     }
 50     void clean()
 51     {
 52         while(len > 1 && !s[len-1]) len--;
 53     }
 54     bign operator * (const bign &b) //*
 55     {
 56         bign c;
 57         c.len = len + b.len;
 58         for(int i = 0; i < len; i++)
 59         {
 60             for(int j = 0; j < b.len; j++)
 61             {
 62                 c.s[i+j] += s[i] * b.s[j];
 63             }
 64         }
 65         for(int i = 0; i < c.len; i++)
 66         {
 67             c.s[i+1] += c.s[i]/10;
 68             c.s[i] %= 10;
 69         }
 70         c.clean();
 71         return c;
 72     }
 73     bign operator *= (const bign &b)
 74     {
 75         *this = *this * b;
 76         return *this;
 77     }
 78     bign operator - (const bign &b)
 79     {
 80         bign c;
 81         c.len = 0;
 82         for(int i = 0, g = 0; i < len; i++)
 83         {
 84             int x = s[i] - g;
 85             if(i < b.len) x -= b.s[i];
 86             if(x >= 0) g = 0;
 87             else
 88             {
 89                 g = 1;
 90                 x += 10;
 91             }
 92             c.s[c.len++] = x;
 93         }
 94         c.clean();
 95         return c;
 96     }
 97     bign operator -= (const bign &b)
 98     {
 99         *this = *this - b;
100         return *this;
101     }
102     bign operator / (const bign &b)
103     {
104         bign c, f = 0;
105         for(int i = len-1; i >= 0; i--)
106         {
107             f = f*10;
108             f.s[0] = s[i];
109             while(f >= b)
110             {
111                 f -= b;
112                 c.s[i]++;
113             }
114         }
115         c.len = len;
116         c.clean();
117         return c;
118     }
119     bign operator /= (const bign &b)
120     {
121         *this  = *this / b;
122         return *this;
123     }
124     bign operator % (const bign &b)
125     {
126         bign r = *this / b;
127         r = *this - r*b;
128         return r;
129     }
130     bign operator %= (const bign &b)
131     {
132         *this = *this % b;
133         return *this;
134     }
135     bool operator < (const bign &b)
136     {
137         if(len != b.len) return len < b.len;
138         for(int i = len-1; i >= 0; i--)
139         {
140             if(s[i] != b.s[i]) return s[i] < b.s[i];
141         }
142         return false;
143     }
144     bool operator > (const bign &b)
145     {
146         if(len != b.len) return len > b.len;
147         for(int i = len-1; i >= 0; i--)
148         {
149             if(s[i] != b.s[i]) return s[i] > b.s[i];
150         }
151         return false;
152     }
153     bool operator == (const bign &b)
154     {
155         return !(*this > b) && !(*this < b);
156     }
157     bool operator != (const bign &b)
158     {
159         return !(*this == b);
160     }
161     bool operator <= (const bign &b)
162     {
163         return *this < b || *this == b;
164     }
165     bool operator >= (const bign &b)
166     {
167         return *this > b || *this == b;
168     }
169     string str() const
170     {
171         string res = "";
172         for(int i = 0; i < len; i++) res = char(s[i]+'0') + res;
173         return res;
174     }
175 };
176 
177 istream& operator >> (istream &in, bign &x)
178 {
179     string s;
180     in >> s;
181     x = s.c_str();
182     return in;
183 }
184 
185 ostream& operator << (ostream &out, const bign &x)
186 {
187     out << x.str();
188     return out;
189 }
190 
191 bign Pow(bign a,int b)
192 {
193     bign ans=1;
194     for (int i=1; i<=b; ++i)
195         ans=ans*a;
196     return ans;
197 }
198 
199 bign f[33],ans;
200 int n,d;
201 
202 int main()
203 {
204     scanf("%d%d",&n,&d);
205     if (!d){puts("1"); return 0;}
206     f[0]=1;
207     for (int i=1; i<=d; ++i)
208         f[i]=Pow(f[i-1],n)+1;
209     cout<<f[d]-f[d-1];
210 }

转载于:https://www.cnblogs.com/refun/p/9806766.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值