中石油问题 F: 斐波那契II(递归双指针)

链接

题意:

小C养了一些很可爱的兔子。
有一天,小C突然发现兔子们都是严格按照伟大的数学家斐波那契提出的模型来进行繁衍:一对兔子从出生后第二个月起,每个月刚开始的时候都会产下一对小兔子。我们假定,在整个过程中兔子不会出现任何意外。
小C把兔子按出生顺序,把兔子们从1开始标号,并且小C的兔子都是1号兔子和1号兔子的后代。如果某两对兔子是同时出生的,那么小C会将父母标号更小的一对优先标号。如果我们把这种关系用图画下来,前六个月大概就是这样的:

image

其中,一个箭头A->B表示A是B的祖先,相同的颜色表示同一个月出生的兔子。
为了更细致地了解兔子们是如何繁衍的,小C找来了一些兔子,并且向你提出了m个问题:她想知道关于每两对兔子ai和bi,他们的最近公共祖先是谁。你能帮帮小C吗?
一对兔子的祖先是这对兔子以及他们父母(如果有的话)的祖先,而最近公共祖先是指两对兔子所共有的祖先中,离他们的距离之和最近的一对兔子。比如,5和7的最近公共祖先是2,1和2的最近公共祖先是1,6和6的最近公共祖先是6。

懒着总结了就这样把。

分析:

我们从图中或者题目中提取信息,就是父亲节点与儿子节点差总是一个斐波那契数。
所以我们先把1e12范围内的斐波那契数写出来,也不是很多,就40多个。
然后就是选择两个中较大的一个数减去小于这个数的斐波那契数就减去,注意是小于等于是不行的,为啥比较完减那?因为这样能明显缩小时间复杂度,不这样每一个数都跑40次,是会超时的。这样找到一样的数,就退出输出即可。

void solve()
{
    scanf("%lld%lld",&n,&m);
    while(1){
        if(n==m) {
            printf("%lld\n",n);
            return ;            
        }
        if(n>m){
            for(int i=num;i>=1;i--){
                if(n>a[i]) {
                    n-=a[i];
                    break;
                }
            }
        }else {
            for(int i=num;i>=1;i--){
                if(m>a[i]) {
                    m-=a[i];
                    break;
                }
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值