bzoj1089 [SCOI2003]严格n元树(dp+高精)

1089: [SCOI2003]严格n元树

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 1899  Solved: 954
[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
/*
定义S[i]代表深度<=i的严格n元树的个数
那么最后S[d]-S[d-1]就是答案
那么对于S[i],我们由S[i-1]递推来,
我们考虑新加一个根节点,然后根节点有n个子节点,每个子节点都可以建一颗深度<=i-1的树,那么每个
子节点都有S[i-1]种选法,那么n个子节点就有S[i-1]^n选法,再加上都不选,就是深度为0的情况
那么S[i]:=(S[i-1]^n)+1;
*/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<iomanip>
using namespace std;
struct long_int{
    int num[3000],cnt;
    void operator = (int y)
    {
        num[1]=y;cnt=1;
    }
    int& operator [] (int x)
    {
        return num[x];
    }
}S[200];
void operator *= (long_int &x,long_int &y)
{
    long_int z=S[199];
    int i,j;
    for(i=1;i<=x.cnt;i++)
        for(j=1;j<=y.cnt;j++)
        {
            z[i+j-1]+=x[i]*y[j];
            z[i+j]+=z[i+j-1]/10000;
            z[i+j-1]%=10000;
        }
    z.cnt=x.cnt+y.cnt;
    if(!z[z.cnt])--z.cnt;
    x=z;
}
void operator ++ (long_int &x)
{
    int i=1;x[1]++;
    while(x[i]==10000)x[i]=0,x[++i]++;
}
long_int operator - (long_int &x,long_int &y)
{
    long_int z=S[199];
    int i;
    for(i=1;i<=x.cnt;i++)
    {
        z[i]+=x[i]-y[i];
        if(z[i]<0) z[i]+=10000,z[i+1]--;
        if(z[i]) z.cnt=i;
    }
    return z;
}
long_int operator ^ (long_int x,int y)
{
    long_int z=S[199];z=1;
    while(y)
    {
        if(y&1) z*=x;
        x*=x;y>>=1;
    }
    return z;
}
ostream& operator << (ostream &os,long_int x)
{
    int i;
    os<<x[x.cnt];
    for(i=x.cnt-1;i;i--)
        os<<setfill('0')<<setw(4)<<x[i];
        //os<<x[i];
    return os;
}
int n,d;
int main()
{
    int i;
    cin>>n>>d;
    if(!d)
    {
        puts("1");return 0;
    }
    S[0]=1;
    for(i=1;i<=d;i++)
        S[i]=S[i-1]^n,++S[i];
    cout<<S[d]-S[d-1]<<endl;
}

 

 

 
 
posted @ 2017-09-15 20:07  安月冷  阅读(224)  评论(0编辑  收藏  举报