【NOIP2017提高组模拟12.10】幻魔皇

来源:互联网 发布:淘宝用绒里图片 编辑:程序博客网 时间:2024/05/01 20:57

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。

The Solution

我们可以先把树给画出来,然后就可以发现一个特殊的性质。


  • deep | 1 | 2 | 3 | 4 | 5|
  • black | 0 | 1 | 1 | 2 | 3|
  • white | 1 | 0 | 1 | 1 | 2|

将就将就着吧。。。不怎么会画表。。。

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

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

首先先定几个数组
white表示白
black表示黑
pre表示1~i层的总共白点数
ans为答案。

1.
白点对的lca为其中的一个白点。我们只需要枚举距离,计算答案即可。
Ans[i]=pre[ni]white[i+1]
(pre[n-i]表示1-(n-i)层总共的白点数,这些白点都可以再向下延伸i个长度,
白点下面连接的是一颗形如从第二层黑点开始的子树,
所以是white[i+1]而不是white[i])
2.
白点对的lca为黑点。这样如果直接枚举两个深度的白点个数相乘是不对的,为什么?
因为你所枚举的两个白点有可能在同一条路径上,这样就不合法了。

所以我们考虑两条路径从lca黑点的黑白两个儿子中各取一个。

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

简单式子可以写成如下
Ans[i+j]=(Ans[i+j]+(ll)(Pre[nmax(i,j)+1]1)(ll)White[i]

CODE

#include <cstdio>#include <iostream>#include <cmath>#include <algorithm>#define fo(i,a,b) for (int i=a;i<=b;i++)using namespace std;typedef long long ll;const int N = 5010,mo = 123456789;int Black[N],Pre[N],White[N],n;ll Ans[N * 2];int main(){    //freopen("raviel.in","r",stdin);    freopen("raviel.out","w",stdout);    scanf("%d",&n);    Black[1] = 1,Black[2] = 1;    fo(i,3,N-5) Black[i] = (Black[i-1] + Black[i-2]) % mo;    White[1] = 1,White[2] = 0,White[3] = 1,White[4] = 1;    fo(i,5,N-5) White[i] = (White[i-1] + White[i-2]) % mo;      fo(i,1,N-5) Pre[i] = (Pre[i-1] + (ll)White[i]) % mo;    fo(i,1,n-1) Ans[i] = (Pre[n-i]*(ll)White[i+1]) % mo;    fo(i,1,n-1)        fo(j,1,n-1) Ans[i+j] = (Ans[i+j] + (ll)(Pre[n-max(i,j)+1] - 1) * (ll)White[i] % mo * (ll)White[j+1] % mo) % mo;    fo(i,1,n*2) printf("%lld ",Ans[i]);    return 0;}
1 0
原创粉丝点击