# BZOJ1089 [SCOI2003]严格n元树 【dp + 高精】

## Description

如果一棵树的所有非叶节点都恰好有n个儿子，那么我们称它为严格n元树。如果该树中最底层的节点深度为d
（根的深度为0），那么我们称它为一棵深度为d的严格n元树。例如，深度为２的严格２元树有三个，如下图：

给出n, d，编程数出深度为d的n元树数目。

## Input

仅包含两个整数n, d( 0   <   n   <   =   32,   0  < =   d  < = 16)

## Output

仅包含一个数，即深度为d的n元树的数目。

【样例输入1】
2 2

【样例输入2】
2 3

【样例输入3】
3 5

## Sample Output

【样例输出1】
3

【样例输出2】
21

【样例输出2】
58871587162270592645034001

# 题解

f[d] = f[d - 1] ^ n + 1【+1考虑只有一个根节点】

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define fo(i,x,y) for (int i = (x); i <= (y); i++)
#define Redge(u) for (int k = head[u]; k != -1; k = edge[k].next)
using namespace std;
const int maxn = 20,maxm = 205,INF = 1000000000;

int N,D;

struct NUM{
int n[maxm],len;
NUM() {memset(n,0,sizeof(n)); len = 0;}
}f[maxn];

inline istream& operator >>(istream& in,NUM& a){
string s;
in>>s;
a.len = s.length();
for (int i = 0; i < a.len; i++) a.n[i] = s[a.len - i - 1] - '0';
return in;
}

inline ostream& operator << (ostream& out,const NUM& a){
if (!a.len) out<<0;
else {
for (int i = a.len - 1; i >= 0; i--) out<<a.n[i];
}
return out;
}

inline NUM operator *(const NUM& a,const NUM& b){
NUM c;
c.len = a.len + b.len + 2;
int carry = 0,temp;
for (int i = 0; i < a.len; i++){
for (int j = 0; j < b.len; j++){
temp = c.n[j + i] + a.n[i] * b.n[j] + carry;
c.n[j + i] = temp % 10;
carry = temp / 10;
}
int len = i + b.len;
while (carry) {
temp = c.n[len] + carry;
c.n[len] = temp % 10;
carry = temp / 10;
len++;
}
}
while (!c.n[c.len - 1]) c.len--;
return c;
}

inline NUM operator + (const NUM& a,const int& b){
NUM c = a;
int temp = c.n[0] + b,carry = temp / 10;
c.n[0] = temp % 10;
for (int i = 1; carry && i < c.len; i++){
temp = c.n[i] + carry;
c.n[i] = temp % 10;
carry = temp / 10;
}
if (carry) c.n[c.len++] = carry;
return c;
}

inline NUM operator - (const NUM& a,const NUM& b){
NUM c;
c.len = a.len;
int carry = 0;
for (int i = 0; i < a.len; i++){
c.n[i] = a.n[i] - b.n[i] + carry;
if (c.n[i] < 0) c.n[i] += 10,carry = -1;
else carry = 0;
}
while (!c.n[c.len - 1]) c.len--;
return c;
}

inline NUM qpow(NUM a,int b){
NUM ans; ans.n[0] = ans.len = 1;
for (; b; b >>= 1,a = a * a)
if (b & 1) ans = ans * a;
return ans;
}

int main()
{
/*cin>>f[0]>>f[1];
cout<<f[0] * f[1]<<endl;*/

cin>>N>>D;
if (!D) {cout<<1<<endl;return 0;}
f[0].n[0] = f[0].len = 1;
for (int i = 1; i <= D; i++){
f[i] = qpow(f[i - 1],N) + 1;
}
cout<<f[D] - f[D - 1]<<endl;
return 0;
}


posted @ 2017-11-06 17:52  Mychael  阅读(125)  评论(0编辑  收藏  举报