題解 斐波那契
阿新 • • 發佈:2021-06-22
考場上找半天規律沒找出來。。。
其實規律可以根據題解推出來:
令一個父親節點的標號為\(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; }