我们定义f[i]表示深度小于等于i的n元树的个数,那么ans=f[d]-f[d-1]
如何转移呢?考虑现在是第i层,我们由第i-1层转移得到,我们考虑从根节点向下构造,根节点下必定连着n个节点,那么每个节点可以向下继续构造一棵深度小于等于i-1的子树,所以一共是f[i-1]^n种构造方法,所以f[i]=f[i-1]+1(啥都不选的情况)
要用高精
代码
//By AcerMo
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define lli long long int
using namespace std;
const int p=1000;
int n,m;
struct high
{
int v[5005],l;
high(){memset(v,0,sizeof(v));}
}f[30];
inline high operator * (high a,high b)
{
high c;
for (int i=1;i<=a.l;i++)
for (int k=1;k<=b.l;k++)
c.v[i+k-1]+=a.v[i]*b.v[k];
c.l=a.l+b.l;
for (int i=1;i<=c.l;i++)
if (c.v[i]>=p)
{
if (i==c.l) c.l++,c.v[i+1]=c.v[i]/p;
else c.v[i+1]+=c.v[i]/p;
c.v[i]%=p;
}
while (c.l>1&&!c.v[c.l]) c.l--;
return c;
}
inline high operator ^ (high a,int b)
{
high c;c.l=1;c.v[1]=1;
for (;b;a=a*a,b>>=1)
if (b&1) c=c*a;
return c;
}
inline high operator + (high a,int b)
{
a.v[1]+=b;int now=1;
while (a.v[now]>=p)
{
a.l=max(a.l,now+1);
a.v[now+1]+=a.v[now]/p;
a.v[now]%=p;now++;
a.l=max(a.l,now);
}
return a;
}
inline high operator - (high a,high b)
{
for (int i=1;i<=a.l;i++)
{
a.v[i]-=b.v[i];
if (a.v[i]<0) a.v[i]+=p,a.v[i+1]--;
}
while (a.l>1&&!a.v[a.l]) a.l--;
return a;
}
inline void coutt(high a)
{
printf("%d",a.v[a.l]);
for (int i=a.l-1;i;i--) printf("%03d",a.v[i]);
return ;
}
signed main()
{
cin>>n>>m;
if (m==0) return puts("1"),0;
f[0].l=1;f[0].v[1]=1;
for (int i=1;i<=m;i++) f[i]=(f[i-1]^n)+1;
return coutt(f[m]-f[m-1]),0;
}