【bzoj2796】 [Poi2012]Fibonacci Representation
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
1070
1070
Sample Output
4
题解
因为F[k]*2=F[k+1]+F[k-2],即存在最优解满足同一个FIB数出现次数不超过1
令l表示小等于n且最大的斐波那契数,r为其后一项,可以暴力或者二分求
dp(n) = min{ dp(n-l) , dp(r-n) } + 1
使用记忆化搜索
1 #include<set> 2 #include<map> 3 #include<iostream> 4 #include<cstdio> 5 #include<cstdlib> 6 #include<cmath> 7 #include<cstring> 8 #include<algorithm> 9 10 #define ll long long 11 #define inf 2e18 12 using namespace std; 13 ll read() 14 { 15 ll x=0,f=1;char ch=getchar(); 16 while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} 17 while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} 18 return x*f; 19 } 20 21 int T,top; 22 ll n,f[1005]; 23 map<ll,int>F; 24 25 int solve(ll n) 26 { 27 if(F[n])return F[n]; 28 int b=lower_bound(f,f+top,n)-f; 29 if(f[b]==n)return 1; 30 return F[n]=min(solve(n-f[b-1]),solve(f[b]-n))+1; 31 } 32 int main() 33 { 34 f[0]=1;f[1]=1; 35 for(int i=2;f[i-1]<=inf;i++,top++) 36 f[i]=f[i-1]+f[i-2]; 37 T=read(); 38 while(T--) 39 { 40 n=read(); 41 printf("%d\n",solve(n)); 42 } 43 }