您的位置:首页 > 其它

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

2017-08-11 12:53 375 查看
Description

  如果一棵树的所有非叶节点都恰好有n个儿子,那么我们称它为严格n元树。如果该树中最底层的节点深度为d(根的深度为0),那么我们称它为一棵深度为d的严格n元树。给出n, d,编程数出深度为d的n元树数目。

Input

  仅包含两个整数n, d( 0 < n < = 32, 0 < = d < = 16)

Output

  仅包含一个数,即深度为d的n元树的数目。

题解:

设f[i]表示深度小于等于i的n元树有多少。可以发现,对于一个n元树,都是由根节点+n个子树组成的,而每个子树又是一个深度小于等于i−1的n元树,再加上一种只有一个根节点的情况,所以有转移方程f[i]=f[i−1]n+1。需要用高精度,发博客主要为了存一存新的高精度模版。(以前都是不用重载运算符的)。

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int M=10000;
struct node
{
int v[10010],l;
}f[20];
node operator * (node a,node b)
{
node c;
c.l=a.l+b.l;
for(int i=1;i<=c.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];
for(int i=1;i<=c.l;i++)
if(c.v[i]>=M)
{
if(i==c.l)c.v[++c.l]=c.v[i]/M;
else c.v[i+1]+=c.v[i]/M;
c.v[i]%=M;
}
while(c.l>1&&!c.v[c.l])c.l--;
return c;
}
node operator + (node a,int b)
{
node c=a;
c.v[1]+=b;
for(int i=1;i<=c.l;i++)
if(c.v[i]>=M)
{
if(i==c.l)c.v[++c.l]=c.v[i]/M;
else c.v[i+1]+=c.v[i]/M;
c.v[i]%=M;
}
return c;
}
node operator - (node a,node b)
{
node c;
c.l=max(a.l,b.l);
for(int i=1;i<=c.l;i++)c.v[i]=0;
for(int i=1;i<=c.l;i++)
{
c.v[i]+=a.v[i]-b.v[i];
if(c.v[i]<0)
{
c.v[i]+=M;
c.v[i+1]--;
if(i+1==c.l&&c.v[i+1]==0)c.l--;
}
}
while(c.l>1&&!c.v[c.l])c.l--;
return c;
}
node p(node x,int y)
{
if(y==1)return x;
node t=p(x,y>>1),ans=t*t;
if(y&1)ans=ans*x;
return ans;
}
int main()
{
int n,d;
scanf("%d%d",&n,&d);
if(d==0){puts("1");return 0;}
f[0].v[1]=1;f[0].l=1;
for(int i=1;i<=d;i++)f[i]=p(f[i-1],n)+1;
node ans=f[d]-f[d-1];
printf("%d",ans.v[ans.l]);
for(int i=ans.l-1;i;i--)
printf("%04d",ans.v[i]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: