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


    题目描述

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

    数据范围

    对于100%的数据n<=5000。

    =w=

    性质:
    以任意一个白点为根作子树时,在这棵子树中,白点和黑点的数量随深度呈斐波那契数列形态。
    设当深度为i时,白点数量为w[i],白点数量前缀和为sum[i],黑点数量前缀和为f[i]。这些可以O(n)预处理。


    我们对贡献分门别类:

    1.lca是白点类
    

    显然当两个点的lca是白点时,其中一个点是这个白点。
    我们以每一个白点为根做子树来计算答案,具体地:

    我们枚举一个i,表示这两个点的距离。
    所有深度在[1,ni]的白点都拥有与它距离为i的儿子,所以都可以对ans[i]作贡献。
    然后这些白点的贡献都是相同的,而且都是w[i+1]

    那么对于一个i,ans[i]+=sum[ni]w[i+1]

    2.lca是黑点类
    

    同样枚举一个i和一个j,其中一个结点与lca距离为i,另一个结点与lca距离为j。
    所有深度在[1,nmax(i,j)]的黑点都可以贡献ans[i+j]

    所以对于i,j,ans[i+j]+=f[nmax(i,j)]w[i]w[j+1]

    代码

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    #define ll long long
    #define ln(x,y) (ll(log(x)/log(y)))
    using namespace std;
    const char* fin="raviel.in";
    const char* fout="raviel.out";
    const ll inf=0x7fffffff;
    const ll mo=123456789;
    const ll maxn=10007;
    ll n,i,j,k;
    ll f[maxn],g[maxn],sum[maxn],ans[maxn];
    int main(){
        freopen(fin,"r",stdin);
        freopen(fout,"w",stdout);
        scanf("%d",&n);
        f[1]=0;
        f[2]=1;
        for (i=3;i<maxn;i++) f[i]=(f[i-2]+f[i-1])%mo;
        for (i=1;i<maxn;i++) f[i]=(f[i]+f[i-1])%mo;
        g[1]=1;
        g[2]=0;
        for (i=3;i<maxn;i++) g[i]=(g[i-2]+g[i-1])%mo;
        for (i=1;i<maxn;i++) sum[i]=(sum[i-1]+g[i])%mo;
        for (i=1;i<n;i++){
            k=n-i;
            ans[i]=(ans[i]+sum[k]*g[i+1])%mo;
        }
        for (i=1;i<n;i++)
            for (j=1;j<n;j++){
                k=n-max(i,j);
                ans[i+j]=(ans[i+j]+f[k]*g[i]%mo*g[j+1])%mo;
            }
        for (i=1;i<=n*2;i++) printf("%lld ",ans[i]);
        printf("
    ");
        return 0;
    }

    =o=

    我认为在做这道题的时候的瓶颈是正确地对贡献分门别类。
    然后要先枚举距离,在根据这个距离计数。
    由于问题是每种距离的个数,那么这个问题决定了这道题必须先枚举距离来计数的特点。
    至今还在纠结正确的枚举方式是怎样。
    还有待决定。

  • 相关阅读:
    正经学C#_循环[do while,while,for]:[c#入门经典]
    Vs 控件错位 右侧资源管理器文件夹点击也不管用,显示异常
    asp.net core 获取当前请求的url
    在实体对象中访问导航属性里的属性值出现异常“There is already an open DataReader associated with this Command which must be
    用orchard core和asp.net core 3.0 快速搭建博客,解决iis 部署https无法登录后台问题
    System.Data.Entity.Core.EntityCommandExecution The data reader is incompatible with the specified
    初探Java设计模式3:行为型模式(策略,观察者等)
    MySQL教程77-CROSS JOIN 交叉连接
    MySQL教程76-HAVING 过滤分组
    MySQL教程75-使用GROUP BY分组查询
  • 原文地址:https://www.cnblogs.com/hiweibolu/p/6714819.html
Copyright © 2020-2023  润新知