您的位置:首页 > 其它

【bzoj2796】 [Poi2012]Fibonacci Representation

2017-08-29 20:14 260 查看
Description

Fib数列0,1,1,2,3,5,8,13,21。

给出一个数字,用FIB数列各项加加减减来得到。例如

10=5+5

19=21-2

17=13+5-1

1070=987+89-5-1

Input

In the first line of the standard input a single positive integer is given (1 <=P<=10) that denotes the number of queries. The following lines hold a single positive integer K each 1<=K<=10^17.

Output

For each query your program should print on the standard output the minimum number of Fibonacci numbers needed to represent the number k as their sum or difference.

Sample Input

1

Sample Output

1070

题解

因为F[k]*2=F[k+1]+F[k-2],即存在最优解满足同一个FIB数出现次数不超过1

令l表示小等于n且最大的斐波那契数,r为其后一项,可以暴力或者二分求

dp(n) = min{ dp(n-l) , dp(r-n) } + 1

使用记忆化搜索

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<set>
#include<ctime>
#include<vector>
#include<cmath>
#include<algorithm>
#include<map>
#define mod 1000000007
#define ll long long
#define inf 2e18
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
map<ll,int>dp;
ll n,f[105];
int num;
int dfs(ll n)
{
if (dp
) return dp
;
int l=1,r=num;
while (l!=r)
{
int mid=(l+r+1)>>1;
if (f[mid]<=n) l=mid;else r=mid-1;
}
if (f[l]==n) return 1;
int ans=dfs(n-f[l]);
if (f[l+1]) ans=min(ans,dfs(f[l+1]-n));
dp
=ans+1;
return dp
;
}
int main()
{
int Case=read();
f[1]=1;f[0]=1;num=1;
for (int i=2;f[i-1]<=inf;i++,num++)
f[i]=f[i-1]+f[i-2];
while (Case--)
{
scanf("%lld",&n);
printf("%d\n",dfs(n));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: