zoukankan      html  css  js  c++  java
  • BZOJ2796[Poi2012]Fibonacci Representation——贪心+二分查找

    题目描述

    给出一个正整数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
     
      因为f[i]=f[i-1]+f[i-2],f[i+1]=f[i]+f[i-1],能得到2f[i]=f[i+1]+f[i-2],所以最优答案一定存在没有一个FIB数被选两次的情况。预处理出FIB数,每一次二分找到最大的小于等于x的FIB数和最小的大于等于x的FIB数,然后求出差的绝对值,递归绝对值小的。至于为什么每次都取最接近x的,这样可以使递归要找的数更小,使答案更优。为什么每次要选最接近x的数?因为我们知道FIB数每一项等于前两项之和,如果每一次不选最大的,因为每一次选的都是越来越小的,那么要想加和等于能选的最大的,就要更多次数。
    #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
    ",find(x));
        }
    }
  • 相关阅读:
    Linux下安装Blender
    自我复制的3D打印机
    ODOO v10.0 自动生成财务凭证的科目设置
    初识Odoo的辅助核算
    Odoo9以后的社区版本和企业版功能上的区别
    06: linux中find查找命令总结
    02: shell中的if、case、for等语句
    01: shell基本使用
    05: 配置yum源
    04: linux基础总结-centos6.5
  • 原文地址:https://www.cnblogs.com/Khada-Jhin/p/9593694.html
Copyright © 2011-2022 走看看