1. 程式人生 > 實用技巧 >【題解】洛谷 P3938 斐波那契【20201013 CSP 模擬賽】

【題解】洛谷 P3938 斐波那契【20201013 CSP 模擬賽】

題目連結

題目連結

題意

第一個月有 \(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;
}