BZOJ1089&&洛谷P4295 [SCOI2003]严格N元树

我们定义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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值