您的位置:首页 > 其它

bzoj 1089 [SCOI2003]严格n元树(DP+高精度)

2016-01-03 21:32 399 查看

1089: [SCOI2003]严格n元树

Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 1250 Solved: 621
[Submit][Status][Discuss]

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

HINT

Source

【思路】

DP+高精度。

设f[i]表示高i的严格n元数的数目,并设S[i]表示f[i]的前缀和。一颗高i的严格n元树有一个根节点以及n个高不超过i-1的子树构成,每个子树方案为S[n-1],则有转移式:

S[i]=(S[i-1]^n)+1

1表示只有一个根的情况。

高精度照着别人的写的,重载运算符,用起来比较方便。

【代码】

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;

const int maxn = 5000+10;
const int rad = 1000;

struct Bign {  int N[maxn],len;  };
void print(Bign a) {
printf("%d",a.N[a.len-1]);
for(int i=a.len-2;i>=0;i--)
printf("%03d",a.N[i]);            //补全位数
putchar('\n');
}
Bign operator *(Bign A,Bign B) {
Bign C;
int lena=A.len,lenb=B.len;
for(int i=0;i<lena+lenb;i++) C.N[i]=0;
for(int i=0;i<lena;i++)
for(int j=0;j<lenb;j++)
C.N[i+j] += A.N[i]*B.N[j];
C.len=A.len+B.len;
for(int i=0;i<C.len;i++)
if(C.N[i]>=rad) {
if(i==C.len-1)
C.len++ , C.N[i+1]=C.N[i]/rad;
else C.N[i+1]+=C.N[i]/rad;
C.N[i]%=rad;
}
while(C.len && !C.N[C.len-1]) C.len--;
return C;
}
Bign operator ^(Bign A,int p) {            //快速幂
Bign C;
C.len=1; C.N[0]=1;
while(p) {
if(p&1) C=C*A; A=A*A;  p>>=1;
}
return C;
}
Bign operator +(Bign A,int x) {
A.N[0]+=x;
int now=0;
while(A.N[now]>=rad) {
A.len=max(A.len,now+1);
A.N[now+1]+=A.N[now]/rad;
A.N[now]%=rad;
now++;
A.len=max(A.len,now);
}
return A;
}
Bign operator-(Bign A,Bign B) {
for(int i=0;i<A.len;i++) {
A.N[i]-=B.N[i];
if(A.N[i]<0)
A.N[i]+=rad , A.N[i+1]--;
}
while(A.len && !A.N[A.len-1]) A.len--;
return A;
}

int n,d;
Bign S[50];

int main() {
scanf("%d%d",&n,&d);
if(!d) { puts("1"); return 0; }
S[0].len=1; S[0].N[0]=1;
for(int i=1;i<=d;i++)
S[i]=(S[i-1]^n)+1;
print(S[d]-S[d-1]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: