首页 > 其他 > 详细

BZOJ2796[Poi2012]Fibonacci Representation——记忆化搜索

时间:2018-09-05 19:23:18      阅读:173      评论:0      收藏:0      [点我收藏+]

题目描述

给出一个正整数x,问x最少能由多少个Fibonacci数加减算出。
例如1070=987+89-5-1,因此x=1070时答案是4。

输入

第一行一个正整数q (q<=10),表示有q组输出。
下面q行每行一个正整数x (x<=4*10^17)。

输出

输出q行,依次表示每个输出的答案。

样例输入

1
1070

样例输出

4
 
  预处理出FIB数,每一次二分找到最大的小于等于x的FIB数和最小的大于等于x的FIB数,然后求出差的绝对值,递归搜索绝对值小的。至于为什么每次都取最接近x的,这样可以使递归要找的数更小,使答案更优。具体证明由于能力有限,没证出来,只能感性理解一下。
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define mid ((l+r)>>1)
using namespace std;
long long f[600];
long long cnt=1;
int t;
long long x;
long long findL(long long x)
{
    int l=1;
    int r=cnt;
    int ans=1;
    while(l<=r)
    {
        if(f[mid]<=x)
        {
            ans=mid;
            l=mid+1;
        }
        else
        {
            r=mid-1;
        }
    }
    return f[ans];
}
long long findR(long long x)
{
    int l=1;
    int r=cnt;
    int ans=1;
    while(l<=r)
    {
        if(f[mid]>=x)
        {
            ans=mid;
            r=mid-1;
        }
        else
        {
            l=mid+1;
        }
    }
    return f[ans];
}
int find(long long x)
{
    long long l=findL(x);
    long long r=findR(x);
    if(l==r)
    {
        return 1;
    }
    if(x-l<=r-x)
    {
        return find(x-l)+1;
    }
    else
    {
        return find(r-x)+1;
    }
}
int main()
{
    f[0]=f[1]=1;
    while(f[cnt-1]<=4e17)
    {
        f[++cnt]=f[cnt-1]+f[cnt-2];
    }
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld",&x);
        printf("%d\n",find(x));
    }
}

BZOJ2796[Poi2012]Fibonacci Representation——记忆化搜索

原文:https://www.cnblogs.com/Khada-Jhin/p/9593694.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!