幻魔皇

幻魔皇

(File IO): input:raviel.in output:raviel.out

Time Limits: 1000 ms Memory Limits: 524288 KB

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

Input
一行一个正整数n。

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

Sample Input

5

Sample Output

0 2 3 3 1 1 0 0 0 0

Data Constraint

  • 对于20%的数据n<=10;
  • 对于40%的数据n<=20;
  • 对于60%的数据n<=30;
  • 对于80%的数据n<=400;
  • 对于100%的数据n<=5000。

解题思路


这是一道神奇的Fibonacci题目,有一个叫Fibonacci Tree的东西,反正就是科大树,还是“嫁接的”有黑果和白果。。。

假设w[i]为第i层白果的个数,b[i]表示第i层黑果的个数, sw[i]=ij=1w[j]      sb[i]=ij=1b[j]
很明显:

  1. 当距离为l的两个点,x,y的lca为x,那么这样的个数为sw[n-l]*w[l+1]
  2. 当距离为l的两个点,x,y的lca为z,那么这样的个数为
    i<k,i<n,ki<nw[i]w[ki+1]sb[nmax(i,ki)]

codes

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const long long maxn=123456789;
long long w[5010],b[5010],sw[5010],sb[5010];
int n;
int main()
{
    freopen("raviel.in","r",stdin);
    freopen("raviel.out","w",stdout);
    scanf("%d",&n);
    w[1]=1;
    w[2]=0;
    b[1]=0;
    b[2]=1;
    sw[1]=sw[2]=1;
    sb[2]=1;
    for(int i=3;i<=n;i++)w[i]=(w[i-1]+w[i-2])%maxn,b[i]=(b[i-1]+b[i-2])%maxn,sb[i]=(sb[i-1]+b[i])%maxn,sw[i]=(sw[i-1]+w[i])%maxn;
    for(int k=1;k<=2*n;k++)
    {
        long long ans=0;
        if(k<n)ans=sw[n-k]*w[k+1]%maxn;
        for(int i=1;i<k;i++)
        {
            if(i>=n)break;
            int j=k-i;
            if(j>=n)continue;
            ans=(ans+(w[i]*w[j+1]%maxn)*sb[n-max(i,j)]%maxn)%maxn;
        }
        printf("%lld ",ans);
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值