【bzoj1089】严格n元树

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

令s[i]为深度不超过i的n元树的数量

显然的s[i]=s[i-1]^n+1

加上高精度即可

#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<queue>
#include<map>
#include<vector>
#include<set>
#define il inline
#define re register
using namespace std;
int n,d;
struct bignum{int len,s[301];
} f[101];
il bignum operator*(bignum a,bignum b){
    bignum c;
    memset(c.s,false,sizeof(c.s));
    c.len=a.len+b.len-1;
    for(int i=1;i<=a.len;i++)
        for(int j=1;j<=b.len;j++){
            c.s[i+j-1]+=a.s[i]*b.s[j];
            c.s[i+j]+=c.s[i+j-1]/10000;
            c.s[i+j-1]%=10000;
        }
    if(c.s[c.len+1]>0) c.len++;
    return c;
}
il void operator++(bignum &a){
    a.s[1]++;
    for(int i=1;i<=a.len;i++){
        a.s[i+1]+=a.s[i]/10000;
        a.s[i]%=10000;
    }
    if(a.s[a.len+1]>0) a.len++;
}
il bignum operator-(bignum a,bignum b){
    bignum c;
    memset(c.s,false,sizeof(c.s));
    c.len=a.len;
    for(int i=1;i<=c.len;i++){
        c.s[i]+=a.s[i]-b.s[i];
        if(c.s[i]<0) c.s[i+1]--;
        c.s[i]=(c.s[i]+10000)%10000;
    }
    return c;
}
il void print(bignum a){
    printf("%d",a.s[a.len]);
    for(int i=a.len-1;i>0;i--)
        printf("%04d",a.s[i]);
    printf("
");
}
int main(){
    scanf("%d%d",&d,&n);
    if(d==0){
        cout<<"1";return 0;
    }
    f[0].len=1;f[0].s[1]=1;
    for(int i=1;i<=n;i++){
        f[i].len=1;f[i].s[1]=1;
        for(int j=1;j<=d;j++){
            f[i]=f[i]*f[i-1];
        //    print(f[i]);
        }
        ++f[i];
    }
    print(f[n]-f[n-1]);
    return 0;
}
原文地址:https://www.cnblogs.com/ExiledPoet/p/6091669.html