标签:通过 char define getc block pos 暴力 efi mat
杨爷对Fibonacci情有独钟
我乍一看是不知道这棵树有什么规律的。但是看久了就会发现一个点跟她爸编号的差值跟她的颜色有关。
其实原理就在这里了。
颜色代表一个点她是第几轮被生的,那么通过暴力搞一搞就能发现有这么一个事实:一个点跟她爸的下标差等于斐波那契数列的第\((col - 1)\)项。
然后就解决了。
故事本来到这里就应该圆满结束的,但我被卡掉了20pts。
正解的做法是类似于树剖求LCA那样用深度大的节点跳上去的做法。
我用的是让一个节点跑上去,用map记录一下,然后另一个节点再跑上去,碰到的第一个有标记的点就是LCA。
我本来也想到类似于正解的做法,但是我不好判断深度啊!
然后出题人这么一句话:
也许……不需要求?
你可以发现编号大的一定不是编号小的的爸爸。
至于求深度……一个一个找父亲找出来就好啦。
我哭了,你呢?
代码:
#include<cstdio>
#include<map>
#include<algorithm>
#define ll long long
const int maxn = 105;
ll fib[maxn];// 59
int n;
ll read()
{
ll ans = 0, s = 1;
char ch = getchar();
while(ch > ‘9‘ || ch < ‘0‘){ if(ch == ‘-‘) s = -1; ch = getchar(); }
while(ch >= ‘0‘ && ch <= ‘9‘) ans = ans * 10 + ch - ‘0‘, ch = getchar();
return s * ans;
}
void init()
{
fib[0] = fib[1] = 1;
for(int i = 2; i <= 59; i++) fib[i] = fib[i - 1] + fib[i - 2];
}
int color(ll x)
{
return std::lower_bound(fib + 1, fib + 59 + 1, x) - fib;
}
ll solve(ll a, ll b)
{
if(a < b) std::swap(a, b);
if(a == b) return a;
return solve(a - fib[color(a) - 1], b);
}
int main()
{
init();
n = read();
for(int i = 1; i <= n; i++)
{
ll a = read(), b = read();
//int posa = color(a), posb = color(b);
//printf("%d %d\n", posa, posb);
printf("%lld\n", solve(a, b));
}
return 0;
}
标签:通过 char define getc block pos 暴力 efi mat
原文地址:https://www.cnblogs.com/Garen-Wang/p/9906118.html