题目传送门


题目描述

小$C$养了一些很可爱的兔子。
有一天,小$C$突然发现兔子们都是严格按照伟大的数学家斐波那契提出的模型来进行繁衍:一对兔子从出生后第二个月起,每个月刚开始的时候都会产下一对小兔子。我们假定,在整个过程中兔子不会出现任何意外。
小$C$把兔子按出生顺序,把兔子们从$1$开始标号,并且小$C$的兔子都是$1$号兔子和$1$号兔子的后代。如果某两对兔子是同时出生的,那么小$C$会将父母标号更小的一对优先标号。
如果我们把这种关系用图画下来,前六个月大概就是这样的:

其中,一个箭头$A\rightarrow B$表示$A$是$B$的祖先,相同的颜色表示同一个月出生的兔子。
为了更细致地了解兔子们是如何繁衍的,小$C$找来了一些兔子,并且向你提出了$m$个问题:她想知道关于每两对兔子$a_i$和$b_i$,他们的最近公共祖先是谁。你能帮帮小$C$吗?

一对兔子的祖先是这对兔子以及他们父母(如果有的话)的祖先,而最近公共祖先是指两对兔子所共有的祖先中,离他们的距离之和最近的一对兔子。比如,$5$和$7$的最近公共祖先是$2$,$1$和$2$的最近公共祖先是$1$,$6$和$6$的最近公共祖先是$6$。


输入格式

输入第一行,包含一个正整数$m$。
输入接下来$m$行,每行包含$2$个正整数,表示$a_i$和$b_i$。


输出格式

输入一共$m$行,每行一个正整数,依次表示你对问题的答案。


样例

样例输入1:

5
1 1
2 3
5 7
7 13
4 12

样例输出1:

1
1
2
2
4

样例输入2:

10
13 5
13 6
13 7
13 8
13 9
13 10
13 11
13 12
13 13
13 14

样例输出2:

5
1
2
1
1
2
1
1
13
1


数据范围与提示

子任务会给出部分测试数据的特点。如果你在解决题目中遇到了困难,可以尝试只解决一部分测试数据。
每个测试点的数据规模及特点如下表:
测试点     $m$                      $a_i,b_i$           特殊性质$1$           特殊性质$2$
  $1$          $\leqslant 11$                  $\leqslant 15$                  $\surd$                         $\surd$
  $2$          $\leqslant 12$                  $\leqslant 15$                  $\times$                         $\times$
  $3$          $\leqslant 13$                  $\leqslant 1000$             $\surd$                         $\times$
  $4$          $\leqslant 14$                  $\leqslant 1000$             $\times$                         $\times$
  $5$          $\leqslant 1005$             $\leqslant{10}^6$                $\surd$                        $\times$
  $6$          $\leqslant 1006$             $\leqslant{10}^6$                $\times$                        $\surd$
  $7$          $\leqslant 1007$             $\leqslant{10}^6$                $\times$                        $\times$
  $8$          $\leqslant 300008$        $\leqslant{10}^{12}$              $\surd$                        $\times$
  $9$          $\leqslant 300009$        $\leqslant{10}^{12}$              $\times$                        $\surd$
  $10$        $\leqslant 300010$        $\leqslant{10}^{12}$              $\times$                        $\times$

特殊性质$1$:保证$a_i,b_i$均为某一个月出生的兔子中标号最大的一对兔子。例如,对于前六个月,标号最大的兔子分别是$1,2,3,5,8,13$。
特殊性质$2$:保证$|a_i,b_i|\leqslant 1$。


题解

考场上$20$分钟切掉这道题,我感觉还是蛮爽的。

$20\%$算法:

直接手动打表,注意$14$是$1$的儿子,而$15$则是$2$的儿子,挺费眼睛的,而且一开始我打了一个表还没打对……

时间复杂度:$\Theta(m)$。

期望得分:$20$分。

$40\%$算法:

直接暴力建树,每次询问都暴力把这棵树重新建一遍来找父亲。

我觉得写这种方法的就是$\times \times \times$,不用管他……

时间复杂度:$\Theta(m\times {|a|}^2\times \log|a|)$($|a|$表示$a_i,b_i$的值域)。

期望得分:$40$分。

$60\%$算法:

考虑$QJ$两个特殊情况:

特殊情况$1$:

  某一个月出生的标号最大的兔子就是斐波那契数列中的一项,画一张图,如下:

  

  我们便会惊喜的发现如果这两只兔子同是斐波那契数列的奇数项或偶数项,那么它们的最近公共祖先就是他们当中较小的那个;否则,它们的最近公共祖先为$1$。

特殊情况$2$:

  如果两只兔子的标号的绝对值等于$1$,则他们的最近公共祖先一定为$1$。

$70\%$算法:

可能细心的你会发现,一个节点一定小于自己儿子的一半,所以我们可以暴力网上找,最多有$\log i$层。

时间复杂度:$\Theta(n+m\log n)$。

期望得分:$70$分。

$100\%$算法:

在考场上,我惊喜的发现了一个规律,一个节点的减去比它小的那个斐波那契数就是他的父亲节点,所以我们可以每次让两个点中更小的那个暴力往上抬,直到相同为止即可。

时间复杂度:$\Theta(60\times m)$。

期望得分:$100$分。


代码时刻

$20\%$算法:

#include<bits/stdc++.h>
using namespace std;
int Map[16][16]={
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
0,1,2,1,1,2,1,2,1,1,2,1,1,2,1,2,
0,1,1,3,1,1,1,1,3,1,1,3,1,1,1,1,
0,1,1,1,4,1,1,1,1,1,1,1,4,1,1,1,
0,1,2,1,1,5,1,2,1,1,2,1,1,5,1,2,
0,1,1,1,1,1,6,1,1,1,1,1,1,1,1,1,
0,1,2,1,1,2,1,7,1,1,2,1,1,2,1,2,
0,1,1,3,1,1,1,1,8,1,1,3,1,1,1,1,
0,1,1,1,1,1,1,1,1,9,1,1,1,1,1,1,
0,1,2,1,1,2,1,2,1,1,10,1,1,2,1,2,
0,1,1,3,1,1,1,1,3,1,1,11,1,1,1,1,
0,1,1,1,4,1,1,1,1,1,1,1,12,1,1,1,
0,1,2,1,1,5,1,2,1,1,2,1,1,13,1,2,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,14,1,
0,1,2,1,1,2,1,2,1,1,2,1,1,2,1,15};
int main()
{
int m;
scanf("%d",&m);
while(m--)
{
int a,b;
scanf("%d%d",&a,&b);
printf("%d\n",Map[a][b]);
}
return 0;
}

$60\%$算法:

#include<bits/stdc++.h>
using namespace std;
int m;
long long fi[60];
int getnum(long long x)
{
int res;
for(int i=1;i<=59;i++)if(fi[i]==x){res=i;break;}
return res;
}
int main()
{
scanf("%d",&m);
fi[0]=fi[1]=1;
for(int i=2;i<=59;i++)
fi[i]=fi[i-1]+fi[i-2];
for(int i=1;i<=m;i++)
{
long long a,b;
scanf("%lld%lld",&a,&b);
if(a==b){printf("%lld\n",a);continue;}
if(a-b==1||b-a==1){puts("1");continue;}
int numa=getnum(a),numb=getnum(b);
if(numa!=-1&&numb!=-1&&(numa&1)==(numb&1))printf("%lld\n",min(a,b));
else puts("1");
}
return 0;
}

$70\%$算法:

#include<bits/stdc++.h>
using namespace std;
int m;
struct rec
{
int nxt;
int to;
}e[1000001];
int head[1000001],cnt;
int t[1000001],tot=1,tmp,depth[1000001],fa[1000001][23];
bool flag;
void add(int st,int to)
{
e[++cnt].to=to;
e[cnt].nxt=head[st];
head[st]=cnt;
}
void build()
{
t[1]=1;
for(int x=1;x<30;x++)
{
tmp=tot;
for(int i=1;i<=tot;i++)
{
t[i]++;
if(t[i]>1)add(i,++tmp);
if(tmp>=1000000)return;
}
tot=tmp;
}
}
void dfs(int x)
{
for(int i=head[x];i;i=e[i].nxt)
{
if(depth[e[i].to])continue;
depth[e[i].to]=depth[x]+1;
fa[e[i].to][0]=x;
for(int j=1;j<=21;j++)
fa[e[i].to][j]=fa[fa[e[i].to][j-1]][j-1];
dfs(e[i].to);
}
}
int LCA(int x,int y)
{
if(depth[x]>depth[y])swap(x,y);
for(int i=21;i>=0;i--)
if(depth[fa[y][i]]>=depth[x])y=fa[y][i];
if(x==y)return x;
for(int i=21;i>=0;i--)
if(fa[x][i]!=fa[y][i])
{
x=fa[x][i];
y=fa[y][i];
}
return fa[x][0];
}
int main()
{
scanf("%d",&m);
build();
depth[1]=1;
dfs(1);
while(m--)
{
int a,b;
scanf("%d%d",&a,&b);
printf("%d\n",LCA(a,b));
}
return 0;
}

$100\%$算法:

#include<bits/stdc++.h>
using namespace std;
int m;
long long fi[61];
long long LCA(long long x,long long y)
{
while(1)
{
if(x==y)return x;
if(x>y){for(int i=1;i<=65;i++)if(fi[i]<x&&fi[i+1]>=x){x-=fi[i];break;}}
else for(int i=1;i<=65;i++)if(fi[i]<y&&fi[i+1]>=y){y-=fi[i];break;}
}
}
int main()
{
fi[1]=fi[2]=1;
for(int i=3;i<=60;i++)
fi[i]=fi[i-1]+fi[i-2];
scanf("%d",&m);
while(m--)
{
long long a,b;
scanf("%lld%lld",&a,&b);
printf("%lld\n",LCA(a,b));
}
return 0;
}
 

rp++

[洛谷P3938]:斐波那契(fibonacci)(数学)的更多相关文章

  1. 洛谷P3938 斐波那契

    题目戳 题目描述 小 C 养了一些很可爱的兔子. 有一天,小 C 突然发现兔子们都是严格按照伟大的数学家斐波那契提出的模型来进行 繁衍:一对兔子从出生后第二个月起,每个月刚开始的时候都会产下一对小兔子 ...

  2. 洛谷 P1306 斐波那契公约数

    洛谷 P1306 斐波那契公约数 题目描述 对于Fibonacci数列:1,1,2,3,5,8,13......大家应该很熟悉吧~~~但是现在有一个很“简单”问题:第n项和第m项的最大公约数是多少? ...

  3. 洛谷P1962 斐波那契数列【矩阵运算】

    洛谷P1962 斐波那契数列[矩阵运算] 题目背景 大家都知道,斐波那契数列是满足如下性质的一个数列: • f(1) = 1 • f(2) = 1 • f(n) = f(n-1) + f(n-2) ( ...

  4. 洛谷 P1306 斐波那契公约数 解题报告

    P1306 斐波那契公约数 题意:求\(Fibonacci\)数列第\(n\)项和第\(m\)项的最大公约数的最后8位. 数据范围:\(1<=n,m<=10^9\) 一些很有趣的性质 引理 ...

  5. 洛谷——P1306 斐波那契公约数

    P1306 斐波那契公约数 题目描述 对于Fibonacci数列:1,1,2,3,5,8,13......大家应该很熟悉吧~~~但是现在有一个很“简单”问题:第n项和第m项的最大公约数是多少? 输入输 ...

  6. 洛谷P1962 斐波那契数列 || P1349 广义斐波那契数列[矩阵乘法]

    P1962 斐波那契数列 大家都知道,斐波那契数列是满足如下性质的一个数列: • f(1) = 1 • f(2) = 1 • f(n) = f(n-1) + f(n-2) (n ≥ 2 且 n 为整数 ...

  7. 洛谷P1755 斐波那契的拆分

    题目背景 无 题目描述 已知任意一个正整数都可以拆分为若干个斐波纳契数,现在,让你求出n的拆分方法 输入输出格式 输入格式: 一个数t,表示有t组数据 接下来t行,每行一个数n(如题) 输出格式: t ...

  8. 洛谷——P2626 斐波那契数列(升级版)矩阵

    题目背景 大家都知道,斐波那契数列是满足如下性质的一个数列: • f(1) = 1 • f(2) = 1 • f(n) = f(n-1) + f(n-2) (n ≥ 2 且 n 为整数). 题目描述 ...

  9. 洛谷 P2626 斐波那契数列(升级版)

    题目背景 大家都知道,斐波那契数列是满足如下性质的一个数列: • f(1) = 1 • f(2) = 1 • f(n) = f(n-1) + f(n-2) (n ≥ 2 且 n 为整数). 题目描述 ...

随机推荐

  1. tensorflow学习笔记七----------RNN

    和神经网络不同的是,RNN中的数据批次之间是有相互联系的.输入的数据需要是要求序列化的. 1.将数据处理成序列化: 2.将一号数据传入到隐藏层进行处理,在传入到RNN中进行处理,RNN产生两个结果,一 ...

  2. 区块链开源实现hyperledger fabric架构详解

    hyperledger fabric是区块链中联盟链的优秀实现,主要代码由IBM.Intel.各大银行等贡献,目前v1.1版的kafka共识方式可达到1000/s次的吞吐量.本文中我们依次讨论:区块链 ...

  3. 权限控制(vue)

    权限控制(vue) 经常会遇到,角色权限控制问题,若是页面控制,倒好说,可如果是当前页面部分可见不可见,这就有些麻烦,如果加上条件就更加苛刻.之前只是简单的v-if进行控制,如今想试试指令(网上一直有 ...

  4. activemq热备与消息丢失

    1. 解压 tar -zxvf apache-activemq-5.12.0-bin.tar.gz2. 改名 mv apache-activemq-5.12.0 activemq3. cd activ ...

  5. 在Visual studio 2017中使用EF6连接MySQL

    在Visual studio 2017中使用EF6连接Mysql ADO.NET Entity Framework 是微软以 ADO.NET 为基础所发展出来的对象关系对应 (O/R Mapping) ...

  6. mysql时间类型

    转自:http://www.cnblogs.com/Matrix54/archive/2012/05/01/2478158.html AVA中获取当前系统时间 一. 获取当前系统时间和日期并格式化输出 ...

  7. C++实现简单的日志记录

    C++实现简单的日志记录 //dlogger.h #ifndef DLOGGER_H #define DLOGGER_H #include <iostream> #include < ...

  8. oracle在没

    db_user表中数据: name age nub 张三 13 13 张三 12 12 张三 12 13 张三 12 13 李四 12 12 李四 12 12 查询重复数据(一条) sql:selec ...

  9. 【问题解决方案】Centos操作文件vim-No write since last change (add ! to override)

    参考链接 CSDN:Centos 7 操作文件No write since last change (add ! to override) 问题描述: :q或者:wq退出失败,显示如No write ...

  10. UITableViewCell选中后子View背景色被Clear

    在TableView中,当cell 处于Hightlighted(高亮)或者Selected(选中)状态下,Cell上的子控件的背景颜色会被 Clear. 解决方法:(4种) 1. 直接设置子控件的 ...