Problem A. 最近公共祖先 ———2019.10.12

我亲爱的学姐冒险跑去为我们送正解

但是,,,,

阿龙粗现了!

cao,,

  

考场期望得分:20   实际得分:20

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

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

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


Notes
样例 1 解释:


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


思路呢,,大概就是这样的:

算法1:

N<=10

直接暴力求树上两点的LCA

期望得分:20

(大概就是我的那20分吧)

代码~:

 1 #include<cmath>
 2 #include<cstdio>
 3 #include<iostream>
 4 using namespace std;
 5 int n;
 6 const int mod=1e9+7;
 7 int deep[10000];
 8 long long ans;
 9 void dfs(int  i,long long t) {
10     if(i>n) return;
11     deep[t]=i;
12     dfs(i+1,t*2),dfs(i+1,t*2+1);
13 }
14 long long lca(long long i,long long j) {
15     while(1) {
16         if(i==j)break;
17         if(i<j)swap(i,j);
18         i/=2;
19     }
20     return deep[i];
21 }
22 long long tot;
23 int main() {
24     freopen("commonants.in","r",stdin);
25     freopen("commonants.out","w",stdout);
26     cin>>n;
27     tot=pow(2,n+1)-1;
28     dfs(0,1);
29     for(int i=1; i<=tot; i++)
30         for(int j=1; j<=tot; j++) {
31             int k=lca(i,j);
32             ans+=k;
33             ans%=mod;
34         }
35     cout<<ans;
36     fclose stdin;
37     fclose stdout;
38     return 0;
39 }
View Code

算法2:

 代码:没得~

算法三:

 

 

 

借土蛋 的代码一用

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 typedef long long ll;
 5 const ll mod = 1e9 + 7;
 6 ll qpow(ll a, ll b){
 7     ll ret = 1;
 8     for(; b; b >>= 1, a = a * a % mod){
 9         if(b & 1) ret = ret * a % mod;
10     }
11     return ret;
12 }
13 ll n;
14 ll f[1000005];
15 int main(){
16     freopen("commonants.in", "r", stdin);
17     freopen("commonants.out", "w", stdout);
18      
19     cin >> n; 
20     printf("%lld
", (qpow(2, 2 * n + 2) - (4 * n % mod + 2) * qpow(2, n) % mod + mod - 2 + mod) % mod);
21     return 0;
22 }
View Code
原文地址:https://www.cnblogs.com/ydclyq/p/11661572.html