1089: [SCOI2003]严格n元树 DP+高精度

可以发现对于一棵深度为 n 的树,这棵树除深度为n的那棵子树外其它子树的高度可以是 0..n ,所以如果用 fi 表示深度为 i 的树的个数可能不太好转移,我们考虑前缀和的形式,令si表示深度 i 的树的个数。
那么一棵深度为 n 的树其实就是根节点加n个深度 <=n1 <script type="math/tex" id="MathJax-Element-368"><=n-1</script>的树,所以有 si=sni1+1 ,然后我们就可以高精度搞一搞了。
重载运算符大法好

#include<iostream>
#include<cstdio>
#define base 10000
using namespace std;
int n,d;
struct node
{
    int num[305];
    int cnt;
    void operator=(int y)
    {
        num[1]=y;
        cnt=1;
    }
    int& operator[](int x)
    {
        return num[x];
    }
}s[20];
inline int read()
{
    int a=0,f=1; char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
    return a*f;
}
node operator*(node a,node b)
{
    node ans=s[19];
    for (int i=1;i<=a.cnt;i++)
        for (int j=1;j<=b.cnt;j++)
        {
            ans[i+j-1]+=a[i]*b[j];
            ans[i+j]+=ans[i+j-1]/base;
            ans[i+j-1]%=base;
        }           
    ans.cnt=a.cnt+b.cnt;
    if (!ans[ans.cnt]) ans.cnt--;
    return ans;
}
node operator^(node a,int b)
{
    node ans=s[19]; ans=1;
    for (;b;b>>=1,a=a*a)
        if (b&1) ans=ans*a;
    return ans;
}
void operator++(node &a)
{
    int now=1; a[1]++;
    while (a[now]==10000)
        a[now]=0,a[++now]++;
}
node operator-(node a,node b)
{
    node ans=s[19];
    for (int i=1;i<=a.cnt;i++)
    {
        ans[i]+=a[i]-b[i];
        if (ans[i]<0) 
            ans[i]+=base,ans[i+1]--;
        if (ans[i])
            ans.cnt=i;
    }
    return ans;
}
void print(node ans)
{
    printf("%d",ans[ans.cnt]);
    for (int i=ans.cnt-1;i;i--)
    {
        if (ans[i]<1000) printf("0");
        if (ans[i]<100) printf("0");
        if (ans[i]<10) printf("0");
        printf("%d",ans[i]);
    }
}
int main()
{
    n=read(); d=read();
    if (!d)
    {
        puts("1");
        return 0;
    }
    s[0]=1;
    for (int i=1;i<=d;i++)
        s[i]=s[i-1]^n,++s[i];
    node ans=s[d]-s[d-1];
    print(ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值