题解 P3938 【斐波那契】
作者:互联网
Solution 斐波那契
题目大意:兔子按照斐波那契提出的模型繁衍,根据它们的父子关系形成一棵树。每次给定两个点,求出它们的 \(lca\)。
贪心
分析:首先暴力建树肯定是会直接上天的
我们发现,对于任何一个不为根的节点,它和它的父亲编号的差值是一个斐波那契数。
证明可以参考 斐波那契进制,LeetCode 类似问题的题解(我是Graphviz找规律发现的)
因此,对于一个数,我们减去它在斐波那契数列里面的前驱,就可以得到它的父亲。
树高不超过 \(60\),直接暴力求 \(lca\) 就可以了。
#include <cstdio>
#include <cctype>
#include <algorithm>
#include <vector>
#pragma GCC optmize(2)
using namespace std;
typedef long long ll;
struct IO{//-std=c++11,with cstdio and cctype
private:
static constexpr int ibufsiz = 1 << 20;
char ibuf[ibufsiz + 1],*inow = ibuf,*ied = ibuf;
static constexpr int obufsiz = 1 << 20;
char obuf[obufsiz + 1],*onow = obuf;
const char *oed = obuf + obufsiz;
public:
inline char getchar(){
#ifndef ONLINE_JUDGE
return ::getchar();
#else
if(inow == ied){
ied = ibuf + sizeof(char) * fread(ibuf,sizeof(char),ibufsiz,stdin);
*ied = '\0';
inow = ibuf;
}
return *inow++;
#endif
}
template<typename T>
inline void read(T &x){
static bool flg;flg = 0;
x = 0;char c = getchar();
while(!isdigit(c))flg = c == '-' ? 1 : flg,c = getchar();
while(isdigit(c))x = x * 10 + c - '0',c = getchar();
if(flg)x = -x;
}
template <typename T,typename ...Y>
inline void read(T &x,Y&... X){read(x);read(X...);}
inline int readi(){static int res;read(res);return res;}
inline long long readll(){static long long res;read(res);return res;}
inline void flush(){
fwrite(obuf,sizeof(char),onow - obuf,stdout);
fflush(stdout);
onow = obuf;
}
inline void putchar(char c){
#ifndef ONLINE_JUDGE
::putchar(c);
#else
*onow++ = c;
if(onow == oed){
fwrite(obuf,sizeof(char),obufsiz,stdout);
onow = obuf;
}
#endif
}
template <typename T>
inline void write(T x,char split = '\0'){
static unsigned char buf[64];
if(x < 0)putchar('-'),x = -x;
int p = 0;
do{
buf[++p] = x % 10;
x /= 10;
}while(x);
for(int i = p;i >= 1;i--)putchar(buf[i] + '0');
if(split != '\0')putchar(split);
}
inline void lf(){putchar('\n');}
~IO(){
fwrite(obuf,sizeof(char),onow - obuf,stdout);
}
}io;
constexpr ll fib[] = {1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368,75025,121393,196418,317811,514229,832040,1346269,2178309,3524578,5702887,9227465,14930352,24157817,39088169,63245986,102334155,165580141,267914296,433494437,701408733,1134903170,1836311903,2971215073,4807526976,7778742049,12586269025,20365011074,32951280099,53316291173,86267571272,139583862445,225851433717,365435296162,591286729879,956722026041,1548008755920};
vector<ll> veca,vecb,tmp;
inline void resolve(vector<ll> &vec,ll x){
tmp.clear();vec.clear();
x--;
while(x){
const ll now = *prev(upper_bound(begin(fib),end(fib),x));
tmp.push_back(now);
x -= now;
}
reverse(tmp.begin(),tmp.end());
ll now = 1;
vec.push_back(now);
for(auto x : tmp){
now += x;
vec.push_back(now);
}
}
inline void solve(){
const ll a = io.readll(),b = io.readll();
if(a == b){
io.write(a,'\n');
return;
}
resolve(veca,a);
resolve(vecb,b);
// for(auto x : veca)io.write(x,' ');
// io.lf();
// for(auto x : vecb)io.write(x,' ');
// io.lf();
for(unsigned int i = 0;;i++){
if(veca[i + 1] != vecb[i + 1] || (i + 1 == veca.size()) || (i + 1 == vecb.size())){
io.write(veca[i],'\n');
return;
}
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("fafa.in","r",stdin);
#endif
const int m = io.readi();
for(int i = 1;i <= m;i++)solve();
return 0;
}
标签:int,题解,void,斐波,io,inline,那契,now,obuf 来源: https://www.cnblogs.com/colazcy/p/14031975.html