luogu3938 斐波那契

题目大意

本题关于兔子的一切单位均是“对”。
一对兔子从出生后第二个月起,每个月刚开始的时候都会产下一对小兔子。
把兔子按出生顺序,把兔子们从1开始标号,并且小C的兔子都是1号兔子和1号兔子的后代。如果某两对兔子是同时出生的,那么小C会将父母标号更小的一对优先标号。
m个问题:两对兔子的最近公共祖先是谁。

思路

直接使用指针建立一棵斐波那契树,空间可受不了。所以我们看看能不能用数学运算来表示父子关系?通过打表找规律,我们发现父节点的编号等于子节点的编号减去小于子节点编号的最大斐波那契数。于是我们知道了一个节点的父亲是谁,朴素地求LCA即可。

#include <cstdio>
#include <cstring>
using namespace std;

#define ll long long

const int MAX_F=60;
ll F[MAX_F];

void GetF(ll *f, int n)
{
	f[0]=f[1]=1;
	for(int i=2; i<=n; i++)
		f[i]=f[i-1]+f[i-2];
}

ll Lca(ll a, ll b)
{
	if(a == b)
		return a;
	for(int i=70; a != b; i--)
	{
		if(F[i] < a)
			a -= F[i];
		if(F[i] < b)
			b -= F[i];
	}
	return a;
}

int main()
{
	GetF(F, 70);
	int opCnt;
	scanf("%d",&opCnt);
	while(opCnt--)
	{
		ll a, b;
		scanf("%lld%lld",&a,&b);
		printf("%lld
",Lca(a, b));
	}
}

原文地址:https://www.cnblogs.com/headboy2002/p/8972084.html