Problem A. 最近公共祖先 (commonants.c/cpp/pas)

注意

Input file: commonants.in

Output file: commonants.out

Time Limit : 0.5 seconds

Memory Limit: 512 megabytes

题面

最近公共祖先\(\text{(Lowest Common Ancestor,LCA)}\)是指在一个树中同时拥有给定的两个点作为后

代的最深的节点。

为了学习最近公共祖先,你得到了一个层数为\(n+1\)的满二叉树,其中根节点的深度为\(0\),其他节点的深度为父节点的深度\(+1\)。你需要求出二叉树上所有点对 \(\texttt{(i,j)}\),(\(i\),\(j\)可以相等,也可以\(i > j\))的最近公共祖先的深度之和对\(10^9+7\)取模后的结果。

输入格式

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

输出格式

一行一个整数表示所有点对 \(\texttt{(i,j)}\),(\(i\),\(j\)可以相等,也可以\(i > j\))的最近公共祖先的深度之和对\(10^9+7\)取模后的结果。

样例

\(\texttt{input\#1}\)

2

\(\texttt{input\#2}\)

19260817

\(\texttt{output\#1}\)

22

\(\texttt{output\#2}\)

108973412

数据范围与提示

样例\(1\)解释:

树一共有\(7\)个节点(一个根节点和两个子节点),其中 \(\texttt{(4,4),(5,5),(6,6),(7,7)}\) 共\(4\)对的最近公共祖先深度为\(2\),\(\texttt{(4,2),(2,4),(5,2),(2,5),(5,4),(4,5),(2,2),(6,3),(3,6),(3,7),(7,3),(6,7),}\)\(\texttt{(7,6),(3,3)}\)共\(14\)对最近公共祖先深度是\(1\),其他的点对最近公共祖先深度为\(0\),所以答案为\(22\)。

对于\(20%\)的数据,\(n \le 10\)。

对于\(50%\)的数据,\(n \le 10^6\) 。

对于\(100%\)的数据,\(1 \le n \le 10^9\) 。


题解

对于一颗有\(n\)层的满二叉树很显然符合以下几点

1.第\(i\)层的点的个数为\(2^i\)。

2.以第\(i\)层的点为根节点的子树大小为\(2^{n-i+1}-1\)。

3.以第\(i\)层的点为\(\text{LCA}\)的点对个数为\(2^{2n-i+1}-2^i\)



观察上面的图(好丑),很明显\(1,2\)都是对的。

对于一颗以第\(i\)层的节点为根的子树:

①它的左子树与右子树上的点的\(\text{LCA}\)都为根节点。所以点对个数为

\[\LARGE\frac{2^{n-i+1}-2}{2} \times \frac{2^{n-i+1}-2}{2}
\]

\[\LARGE= (2^{n-i}-1) \times (2^{n-i}-1)
\]

\[\LARGE= 2^{2n-2i}-2^{n-i+1}+1
\]

②这棵子树的左子树与根节点的\(\text{LCA}\)都为根节点。右子树也是。所以有\(2^{n-i+1}-2\)对点。

③根节点与根节点的\(\text{LCA}\)也是根节点,点对个数为1。

点对\(\texttt{(u,v)}\)与点对\(\texttt{(v,u)}\)在\(u \neq v\)时是两个不同的点对。

所以将上述①②相加乘二再加③就是以子树根节点为\(\text{LCA}\)的点对的数量为:

\[\LARGE 2^{2n-2i+1}-1
\]

因为第\(i\)层的点的个数为\(2^i\)。所以以第\(i\)层的点为\(\text{LCA}\)的点对个数为:

\[\LARGE 2^{2n-i+1}-2^i
\]

因为一共有\(n+1\)层,从\(0-n\)层,所以答案为:

\[\LARGE \sum_{i=0}^{n} (2^{2n-i+1}-2^i) \times i
\]

\[\LARGE =\sum_{i=0}^{n} i \times 2^{2n-i+1}-i \times 2^i
\]

但这样复杂度为\(\Theta (nlog_n)\)过不了。。将上面的式子展开:

\[\LARGE \sum_{i=0}^{n} i \times 2^{2n-i+1} - \sum_{i=0}^{n} i \times 2^i
\]

\[\LARGE T_n=\sum_{i=0}^{n} i \times 2^{2n-i+1}
\]

\[\LARGE =2^{2n} + 2 \times 2^{2n-1} + 3 \times 2^{2n-2}+...+n \times 2^{n+1}
\]

\[\LARGE 2T_n=2^{2n+1} + 2 \times 2^{2n} + 3 \times 2^{2n-1}+...+n \times 2^{n+2}
\]

\[\Large 2T_n-T_n=2^{2n+1} + 2^{2n} + 2^{2n-1}+...+2^{n+2} - n \times 2^{n+1}
\]

\[\LARGE T_n=2^{2n+1} + 2^{2n} + 2^{2n-1}+...+2^{n+2} - n \times 2^{n+1}
\]

很明显前\(n\)项为等比数列,利用等比数列求和公式可以很快求出。

\[\LARGE T_n=\sum_{i=0}^{n} i \times 2^i
\]

\[\LARGE =2 + 2 \times 2^2 + 3 \times 2^3 +...+ n \times 2^n
\]

\[\LARGE 2T_n=2^2 + 2 \times 2^3 + 3 \times 2^4 + ... + n \times 2^{n+1}
\]

\[\LARGE T_n-2T_n=2 + 2^2 + 2^3 +...+2^n- n \times 2^{n+1}
\]

很明显也是等比数列。将这两个相加就是答案了。

快速幂是\(log\)。所以复杂度是\(\Theta(log_n)\)


\(Code\)

#include<bits/stdc++.h>
typedef long long ll;
ll n;
const ll mod=1000000007; inline void read(ll &T) {
ll x=0;bool f=0;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=!f;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
T=f?-x:x;
} inline ll qpow(ll a,ll b) {
ll ans=1,base=a;
while(b) {
if(b&1) ans=(ans*base)%mod;
base=(base*base)%mod;
b>>=1;
}
return ans%mod;
} int main() {
read(n);
ll qwq=(((2*qpow(2,2*n+1))%mod-qpow(2,n+2)+5*mod)%mod-n*qpow(2,n+1)+5*mod)%mod;
ll qaq=((((2*qpow(2,n))%mod)-2+5*mod)%mod-n*qpow(2,n+1)+5*mod)%mod;
//std::cout<<qwq<<'\n'<<qaq<<'\n';
std::cout<<(qwq+qaq+5*mod)%mod;//加上一个模数再取模是为了处理负数的情况
return 0;
}

【CSP-S膜你考】最近公共祖先 (数学)的更多相关文章

  1. 【CSP-S膜你考】即时战略(模拟)

    Problem B. 即时战略 (rts.c/cpp/pas) 注意 Input file: rts.in Output file: rts.out Time Limit : 2 seconds Me ...

  2. 8.3考试总结(NOIP模拟19)[最长不下降子序列·完全背包问题·最近公共祖先]

    一定要保护自己的梦想,即使牺牲一切. 前言 把人给考没了... 看出来 T1 是一个周期性的东西了,先是打了一个暴力,想着打完 T2 T3 暴力就回来打.. 然后,就看着 T2 上头了,后来发现是看错 ...

  3. poj 1330 Nearest Common Ancestors(LCA:最近公共祖先)

    多校第七场考了一道lca,那么就挑一道水题学习一下吧= = 最简单暴力的方法:建好树后,输入询问的点u,v,先把u全部的祖先标记掉,然后沿着v->rt(根)的顺序检查,第一个被u标记的点即为u, ...

  4. Solution: 最近公共祖先·一 [hiho一下 第十三周]

    题目1 : 最近公共祖先·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho最近发现了一个神奇的网站!虽然还不够像58同城那样神奇,但这个网站仍然让小Ho乐在其中 ...

  5. 「LuoguP3379」 【模板】最近公共祖先(LCA)

    题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...

  6. [知识点]最近公共祖先LCA

    UPDATE(20180822):重写部分代码. 1.前言 最近公共祖先(LCA),作为树上问题,应用非常广泛,而求解的方式也非常多,复杂度各有不同,这里对几种常用的方法汇一下总. 2.基本概念和暴力 ...

  7. LCA最近公共祖先 ST+RMQ在线算法

    对于一类题目,是一棵树或者森林,有多次查询,求2点间的距离,可以用LCA来解决.     这一类的问题有2中解决方法.第一种就是tarjan的离线算法,还有一中是基于ST算法的在线算法.复杂度都是O( ...

  8. 【转】最近公共祖先(LCA)

    基本概念 LCA:树上的最近公共祖先,对于有根树T的两个结点u.v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u.v的祖先且x的深度尽可能大. RMQ:区间最小值查询问题.对于长度为n的 ...

  9. 【并查集】【树】最近公共祖先LCA-Tarjan算法

    最近公共祖先LCA 双链BT 如果每个结点都有一个指针指向它的父结点,于是我们可以从任何一个结点出发,得到一个到达树根结点的单向链表.因此这个问题转换为两个单向链表的第一个公共结点(先分别遍历两个链表 ...

随机推荐

  1. XAML加载的四种方式

    XAML加载与编译可以分为四种: 仅使用代码进行WPF程序的生成 使用代码和未编译的标记 使用代码和编译过的BAML 1.只是用代码进行窗体的生成:优点是可以随意定制应用程序,缺点是没有可视化编辑窗口 ...

  2. C# vb .NET读取识别条形码线性条码EAN-13

    EAN-13是比较常见的条形码编码规则类型的一种.如何在C#,vb等.NET平台语言里实现快速准确读取该类型条形码呢?答案是使用SharpBarcode! SharpBarcode是C#快速高效.准确 ...

  3. Centos7安装Tomcat7,并上传JavaWeb项目

    一.需要的工具(其他连接工具也行) 1.Xshell 2.XFTP 1.1首先将Tomcat7的压缩文件利用XFTP上传到Centos7系统上的 /etc/local/tomcat中 1.2 解压文件 ...

  4. Java基础篇(下)

    6.Java面向对象的三个特征与含义 三大特征是:继承.封装和多态. (1)继承的概念 继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类. 继承就是子类继承父类的特征和行为,使得 ...

  5. CodeForces 536D Tavas in Kansas

    洛谷题目页面传送门 & CodeForces题目页面传送门 A和B在一张无向连通图\(G=(V,E),|V|=n,|E|=m\)上玩一个游戏,节点\(i\)有一个权值\(v_i\).A.B分别 ...

  6. hibernate Criteria中多个or和and的用法 and ( or or)

    /s筛选去除无效数据 /*      detachedCriteria.add( Restrictions.or( Restrictions.like("chanpin", &qu ...

  7. js设置全局变量与读取全局变量

    方法1: 设置: var a = 1; 读取: a window.a window['a'] 方法2: 设置: window.b=2; 读取: b window.b window['b'] 方法3: ...

  8. 什么是MVC框架?

    1.什么是mvc Model View Controller,是模型-视图-控制器的缩写,一种软件设计典范,用一种业务逻辑.数据.界面显示分离的方法组织代码,将业务逻辑聚集到一个组件里,在改进和个性化 ...

  9. 对List集合中的元素进行排序

    原文:http://blog.csdn.net/veryisjava/article/details/51675036 Collections对List集合中的数据进行排序 有时候需要对集合中的元素按 ...

  10. 解决apscheduler报错:Run time of job …… next run at: ……)” was missed by

    在Django中使用apscheduler django_apscheduler 实现定时任务, 来完成数据拉取. 一段时间后发现数据量对不上,遂查日志 发现报错如下: Run time of job ...