题解 斐波那契
考场上找半天规律没找出来。。。
其实规律可以根据题解推出来:
令一个父亲节点的标号为\(j\)
考虑它在第i代所生的孩子,此时已有\(fib[i-1]\)只兔子,其中标号\(\leqslant fib[i-2]\)的兔子能生育
所以它在这一代的孩子为标号为\(fib[i-1]+j\)
那就可以逆推,一个标号减去严格小于它的第一个斐波那契数所得,即为其父亲标号
所以可以暴力上翻了。
不建议试图对斐波那契数建树并利用倍增优化过程,这样需要加极多特判别问我怎么知道的
Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 1000100
#define ll long long
#define ld long double
#define usd unsigned
#define ull unsigned long long
//#define int long long
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
char buf[1<<21], *p1=buf, *p2=buf;
inline ll read() {
ll ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans;
}
int m;
namespace force{
int lim, size=1;
int head[N], esiz, fa[N][25], dep[N], lg[N];
bool vis[N];
struct que{ll a, b; inline void build(int k, int j) {a=k; b=j;}}que[N];
queue<int> q, q2;
int lca(int a, int b) {
if (dep[a]<dep[b]) swap(a, b);
while (dep[a]>dep[b]) a=fa[a][lg[dep[a]-dep[b]]-1];
if (a==b) return a;
for (int i=lg[dep[a]]-1; i>=0; --i)
if (fa[a][i]!=fa[b][i])
a=fa[a][i], b=fa[b][i];
return fa[a][0];
}
void solve() {
int t;
m=read();
for (int i=1,a,b; i<=m; ++i) {
a=read(); b=read();
lim=max(lim, max(a, b));
que[i].build(a, b);
}
for (int i=1; i<=lim; ++i) lg[i]=lg[i-1]+(1<<lg[i-1]==i);
dep[1]=1; q.push(1);
while (size<=lim) {
//cout<<size<<endl;
t=q.front(); q.pop();
//cout<<"t: "<<t<<endl;
if (t==1) while (!q2.empty()) q.push(q2.front()), q2.pop();
if (!vis[t]) {vis[t]=1; q.push(t); continue;}
++size;
//if (t==1) cout<<size<<endl;
dep[size]=dep[t]+1;
fa[size][0]=t;
for (int i=1; i<23; ++i)
if (dep[size]>=(1<<i)) fa[size][i]=fa[fa[size][i-1]][i-1];
else break;
q.push(t);
q2.push(size);
}
for (int i=1; i<=m; ++i)
printf("%d\n", lca(que[i].a, que[i].b)); //, cout<<"lca "<<que[i].a<<' '<<que[i].b<<endl;
}
}
namespace task{
ll fib[65];
inline ll find(ll a) {return a-*(lower_bound(fib+1, fib+61, a)-1);}
void solve() {
ll a, b, f, frk, af, bf;
m=read();
fib[0]=fib[1]=fib[2]=1;
for (int i=3; i<=60; ++i) fib[i]=fib[i-1]+fib[i-2];
//for (int i=1; i<=20; ++i) cout<<fib[i]<<' '; cout<<endl;
for (int i=1; i<=m; ++i) {
a=read(); b=read();
if (a==b) {printf("%lld\n", a); continue;}
if (a==1||b==1) {puts("1"); continue;}
while (a!=b) {
if (a>b) a=find(a);
else b=find(b);
}
printf("%lld\n", a);
}
}
}
signed main()
{
#ifdef DEBUG
freopen("1.in", "r", stdin);
#endif
task::solve();
return 0;
}