博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ2796[Poi2012]Fibonacci Representation——贪心+二分查找
阅读量:6815 次
发布时间:2019-06-26

本文共 1399 字,大约阅读时间需要 4 分钟。

题目描述

给出一个正整数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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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)); }}

转载于:https://www.cnblogs.com/Khada-Jhin/p/9593694.html

你可能感兴趣的文章
网络提速(最短路)
查看>>
Spring整合MongoDB实现多个or的范围查询
查看>>
python安装包模块
查看>>
swap内存交换空间构建
查看>>
无标题文章正则表达式
查看>>
存储因管理员策略问题显示脱机解决方法
查看>>
Android Intent Action 大全
查看>>
4412开发板支持GPS高强度信号
查看>>
微信小程序开发-概述
查看>>
SSM(Spring,SpringMVC,MyBatis)用户登录
查看>>
vc代码获取文件版本信息
查看>>
mysql连接小错误一例
查看>>
奇怪的“考生”:中美高考,我都考一考!
查看>>
IBM P系列小型机故障的基本定位
查看>>
The connection cannot proceed because authentication is not enabled
查看>>
7天 搞定 ASP.NET MVC - 第3天
查看>>
云桌面无法识别ica文件
查看>>
分区 fdisk
查看>>
docker registry v2 nginx 安全访问控制
查看>>
Linux中查看各文件夹大小命令du -h --max-depth=1
查看>>