码迷,mamicode.com
首页 > 其他好文 > 详细

P3938 斐波那契

时间:2018-11-04 23:05:21      阅读:242      评论:0      收藏:0      [点我收藏+]

标签:通过   char   define   getc   block   pos   暴力   efi   mat   

去年模拟赛D1T1

杨爷对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;
}

P3938 斐波那契

标签:通过   char   define   getc   block   pos   暴力   efi   mat   

原文地址:https://www.cnblogs.com/Garen-Wang/p/9906118.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!