test 8 Problem C: [noip2016十连测第八场]幻魔皇 (递推+乱搞)

Problem C: [noip2016十连测第八场]幻魔皇

Time Limit: 10 Sec   Memory Limit: 512 MB
Submit: 10   Solved: 5
[ Submit][ Status][ Web Board]

Description

http://www.lydsy.com/JudgeOnline/upload/201610/test8888.rar

幻魔皇拉比艾尔很喜欢斐波那契树,他想找到神奇的节点对。所谓斐波那契树,根是一个白色节点,每个白色节点
都有一个黑色节点儿子,而每个黑色节点则有一个白色和一个黑色节点儿子。神奇的节点对则是指白色节点对。请
问对于深度为n的斐波那契树,其中距离为i的神奇节点对有多少个?拉比艾尔需要你对于1<=i<=2n的所有i都求出
答案。

Input

一行一个正整数n,n<=5000

Output

一行2n个整数表示答案,对123456789取模。

Sample Input

5 

Sample Output

0 2 3 3 1 1 0 0 0 0​

HINT

[ Submit][ Status]

题解:递推+乱搞

斐波那契树有一些非常好的性质。

deep    1     2      3      4      5      

black    0    1       1      2      3

white    1    0       1      1      2

我们发现每层的黑点数满足斐波那契,每层的白点从第二层开始满足斐波那契数列。

我们分成两种情况进行讨论。

(1) 白点对的lca为其中的一个白点。我们只需要枚举距离,计算答案即可。

ans[i]=sum[n-i]*w[i+1]  (sum[n-i]表示1-(n-i)层总共的白点数,这些白点都可以再向下延伸i个长度,白点下面连接的是一颗形如从第二层黑点开始的子树,所以是w[i+1]而不是w[i])

(2)白点对的lca为黑点。这样如果直接枚举两个深度的白点个数相乘是不对的,为什么?因为你所枚举的两个白点有可能在同一条路径上,这样就不合法了。所以我们考虑两条路径从lca黑点的黑白两个儿子中各取一个。

那么原本我们要求两条长度为i,j的路径合成一个i+j的路径,就变成了从黑儿子中选一条长度i-1的路径,从白儿子中选一条长度j-1的路径。他的黑儿子是一颗形如从第二层黑点开始的子树,所以个数为w[i+1],而白儿子就是从第一层直接开始的路径,也就是w[i]实际表示的是与lca黑点相距i+1的白点,所以个数是w[j].总之这块比较难想,画一画树就明白了。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 10003
#define p 123456789
#define LL long long
using namespace std;
LL n,m,f[N],w[N],b[N],sum[N];
LL ans[N];
int main()
{
	scanf("%I64d",&n);
	f[1]=1; f[2]=1;
	for (int i=3;i<=5000;i++)
	 f[i]=(f[i-1]+f[i-2])%p;
	w[1]=1; w[2]=0; w[3]=1; w[4]=1;
	for (int i=5;i<=5000;i++) w[i]=(w[i-1]+w[i-2])%p;
	for (int i=1;i<=5000;i++) sum[i]=(sum[i-1]+w[i])%p;
	for (int i=1;i<n;i++)
	 ans[i]=sum[n-i]*w[i+1]%p; //找到n-i层的白点,然后向下走i层。
    for (int i=1;i<n;i++)
     for (int j=1;j<n;j++)
      ans[i+j]=(ans[i+j]+(sum[n-max(i,j)+1]-1)*w[i]%p*w[j+1])%p;
	for (int i=1;i<=2*n;i++)
	 cout<<ans[i]<<" ";
	cout<<endl;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值