【bzoj2796】 [Poi2012]Fibonacci Representation

来源:互联网 发布:手机淘宝等级查询 编辑:程序博客网 时间:2024/06/04 18:42

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 2e18using 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[n]) return dp[n];    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[n]=ans+1;    return dp[n];}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;}
原创粉丝点击