题意
第一个月有 \(1\) 对兔子,编号为 \(1\),之后每个月,年龄大于 \(1\) 的兔子会生一对新的兔子(如同斐波那契数列的模型),新生兔子按出生时间编号,出生时间相同则按双亲编号小的编号小。\(m\) 次询问 \(x\) 和 \(y\) 的最近公共祖先。\(m\leq 3\times 10^5\),\(x,y\leq 10^{12}\)。
题解
\(x\) 的父亲为 \(x\) 减去小于 \(x\) 的最大的斐波那契数。树深是 \(\log\) 级别的,于是暴力往上跳即可。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll getint(){
ll ans=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
ans=ans*10+c-'0';
c=getchar();
}
return ans*f;
}
ll f[62],cnt=2;
int main(){
// freopen("t1.in","r",stdin);
// freopen("t1.out","w",stdout);
int m=getint();
f[0]=f[1]=1;
for(cnt=2;f[cnt-1]<=1e12;cnt++){
f[cnt]=f[cnt-1]+f[cnt-2];
}
while(m --> 0){
ll x=getint(),y=getint();
int p=cnt-1;
while(x!=y){
(x<y)?swap(x,y),0:0;
while(f[p]>=x)--p;
x-=f[p];
}
printf("%lld\n",x);
}
return 0;
}