bzoj1089严格n元树——DP+高精度

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1089

f[d]为深度小于等于d的树的个数;

从根节点出发,有n个子树,乘法原理可以得到 f[d] = f[d-1] ^ n + 1 ,加1是因为也可以没有根节点;

需要高精度,直接重载运算符十分方便。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int const rad=1000;
int n,d;
struct data{
    int v[5005],l;
}f[30];
data operator*(data a,data b)
{
    data c;
    for(int i=1;i<=a.l+b.l;i++)c.v[i]=0;
    for(int i=1;i<=a.l;i++)
        for(int j=1;j<=b.l;j++)
            c.v[i+j-1]+=a.v[i]*b.v[j];
    c.l=a.l+b.l;
    for(int i=1;i<=c.l;i++)
    {
        if(c.v[i]>=rad)
        {
            if(i==c.l)
            {
                c.l++;
                c.v[c.l]=c.v[i]/rad;
            }
            else c.v[i+1]+=c.v[i]/rad;
            c.v[i]%=rad;
        }
    }
    while(c.v[c.l]==0&&c.l>1)c.l--;
    return c;
}
data operator^(data a,int n)
{
    data c;
    c.l=1;c.v[1]=1;
    while(n)
    {
        if(n&1)c=c*a;
        a=a*a;
        n>>=1;
    }
    return c;
}
data operator+(data a,int x)
{
    a.v[1]+=x;
    int now=1;
    while(a.v[now]>=rad)a.v[now+1]+=a.v[now]/rad,a.v[now]%=rad,now++;
    a.l=max(a.l,now);
    return a;
}
data operator-(data a,data b)
{
    for(int i=1;i<=a.l;i++)
    {
        a.v[i]-=b.v[i];
        if(a.v[i]<0)
        {
            a.v[i]+=rad;
            a.v[i+1]--;
        }
    }
    while(a.v[a.l]==0&&a.l>1)a.l--;
    return a;
}
//void print(data a)
//{
//  for(int i=a.l;i;i--)
//      printf("%d",a.v[i]);
//}
void print(data a)
{
    printf("%d",a.v[a.l]);
    for(int i=a.l-1;i;i--)
        printf("%03d",a.v[i]);
    printf("\n");
}
int main()
{
    scanf("%d%d",&n,&d);
    if(d==0)
    {
        printf("1");return 0;
    }
    f[0].l=1;f[0].v[1]=1;
    for(int i=1;i<=d;i++)
        f[i]=(f[i-1]^n)+1;//+   必须加括号!!! 
    print(f[d]-f[d-1]);
    return 0;
}

 

posted @ 2018-06-04 18:55  Zinn  阅读(125)  评论(0编辑  收藏  举报