幻魔皇 解题报告

幻魔皇

问题描述

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

输入格式

一行一个正整数 \(n\)

输出格式

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

数据范围与约定

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


思路:按点对的\(\tt{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}\)

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

\(ans_i=f_i\sum\limits_{j=0}^{n-i-1}f_j\)

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

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

\(ans_i=\sum\limits_{k=1}^if_{k-1}\times g_{i-k-2}\sum\limits_{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

posted @ 2018-11-01 17:35  露迭月  阅读(229)  评论(0编辑  收藏  举报