幻魔皇——解题报告

题目链接http://172.25.37.251/problem/112
题目大意:斐波那契树,根是一个白色节点,每个白色节点都有一个黑色节点儿子,而每个黑色节点则有一个白色和一个黑色节点儿子。神奇的节点对则是指白色节点对。对于深度为 n 的斐波那契树,其中距离为 i 的神奇节点对有多少个?需要你对于 1<=i<=2n 的所有 i 都求出答案。
题目分析
1.通过仔细观察我们可以发现,只要你话画的时候左右子树的画法不变,你画出的树,对于任意一个根为黑色节点的树,在等深度下,他们都是相同的。如图:
在这里插入图片描述
2.当选择白色点对的时候我们可以发现,他们可以分为两种情况:
❶LCA为其中一个白色点❷LCA为一个黑色点。
我们可以分开来计算这两种情况的解。
3.由斐波拉契树的特性可以知道,某一深度的黑色白色点数一定是一个斐波拉契数。
解题过程
1.预处理处斐波拉契数,也就是第i层的白色点数f[i]。并处理一个前缀和sum[i]。
2.处理LCA为白色的情况,如果长度为i那么显然只有深度h≥n-i的白色点才能作为这个LCA,那么我们可以枚举长度,计算出答案,如下:

for(ll i=1;i<n;i++)
	ans[i]=(sum[n-i-1]+1)*f[i]%mod;//+1是因为需要最开始的白色点,-1是因为深度和斐波拉契数列要匹配

3.处理LCA为黑色的情况,我们只有分别枚举两个白色点在这颗子树的深度,如果长度为i和j那么能够使用的黑色点深度h≥n-max(i-j)。如下:

for(ll i=1;i<n;i++)
	for(ll j=1;j<n;j++)
		ans[i+j]=(ans[i+j]+sum[n-max(i,j)]*f[i-1]%mod*f[j])%mod;

解题结束。
正解代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define mod 123456789

using namespace std;
typedef long long ll;
const ll maxn=10010;
ll n,ans[maxn],f[maxn],sum[maxn];
int main()
{
	scanf("%lld",&n);
	f[0]=1;
	for(ll i=2;i<=n;i++)
	{
		f[i]=(f[i-1]+f[i-2])%mod;
		sum[i]=(sum[i-1]+f[i])%mod;
	}
	for(ll i=1;i<n;i++)
		ans[i]=(sum[n-i-1]+1)*f[i]%mod;
	for(ll i=1;i<n;i++)
		for(ll j=1;j<n;j++)
			ans[i+j]=(ans[i+j]+sum[n-max(i,j)]*f[i-1]%mod*f[j])%mod;
	for(ll i=1;i<=2*n;i++)
		printf("%lld ",ans[i]);
		
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值