幻魔皇 解题报告

幻魔皇

问题描述

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

输入格式

一行一个正整数 (n)

输出格式

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

数据范围与约定

对于(20\%)的数据 (nle 10)
对于(40\%)的数据 (nle 20)
对于(60\%)的数据 (nle 30)
对于(80\%)的数据 (nle 400)
对于(100\%)的数据 (nle 5000)


思路:按点对的( t{LCA})为黑点和白点分开统计。

(f_i)表示根节点为白色距离根节点为(i)的白点个数

(F_i)表示根节点为白色距离根节点为(i)的黑点个数

(g_i)表示根节点为黑色距离根节点为(i)的白点个数

显然有(g_i)为斐波那契数列。

另有递推(f_i=F_{i-1},F_i=F_{i-1}+f_{i-1})

对白色的( t{LCA}),枚举距离(i)

(ans_i=f_isumlimits_{j=0}^{n-i-1}f_j)

表示层数还够的点的个数 乘上 以这个点为根的距离根为(i)的白点个数

对黑色的( t{LCA}),我们还是枚举距离(i),并且找( t{Ta})的两个儿子的信息来统计,枚举其中一个儿子的长度为(k)

(ans_i=sumlimits_{k=1}^if_{k-1} imes g_{i-k-2}sumlimits_{j=1}^{n-1-max(k-1,i-k-1)}F_j)

分别表示左右儿子对应长度的点数和黑点数

前缀和优化一下,复杂度(O(n^2))

总结:统计要想办法划分状态


Code:

#include <cstdio>
const int mod=123456789;
const int N=3010;
int f[N],F[N],g[N],s1[N],s2[N],ans[N],n;
#define rep(i,a,b) for(int i=a;i<=b;i++)
int max(int x,int y){return x>y?x:y;}
int main()
{
    scanf("%d",&n);
    g[1]=g[2]=1;
    rep(i,3,n) g[i]=(g[i-1]+g[i-2])%mod;
    s1[0]=f[0]=1;
    rep(i,1,n) f[i]=F[i-1],F[i]=(F[i-1]+f[i-1])%mod;
    rep(i,1,n) s1[i]=(s1[i-1]+f[i])%mod,s2[i]=(s2[i-1]+F[i])%mod;
    rep(i,1,(n-1)) (ans[i]+=1ll*s1[n-i-1]*f[i]%mod)%=mod;
    rep(i,1,(n<<1))
        rep(k,1,i)
            (ans[i]+=1ll*f[k-1]*g[i-k-1]%mod*s2[n-2-max(k-1,i-k-1)]%mod)%=mod;
    rep(i,1,(n<<1)) printf("%d ",ans[i]);
    return 0;
}

2018.11.1

原文地址:https://www.cnblogs.com/butterflydew/p/9890613.html