斐波那契fib
輸入N和N個數(N<=10,每個數<=10^17),對于每個數,要輸出能用幾個斐波那契數加加減減得到
樣例輸入:
3
5
10
1070
樣例輸出:
1
2
4
直接拷題解:
fib[i]表示斐波那契數列的第i項,兩個結論:
1.一個數不能出現兩次:fib[i]+fib[i]=fib[i-2]+fib[i+1],而fib[2]+fib[2]=fib[3],將出現兩次的數不斷拆分,答案只會減小不會變大。
2.相鄰兩項不能同時取:fib[i]-fib[i-1]=fib[i-2],fib[i]+fib[i-1]=fib[i+1],將相鄰的數不斷拆分,答案只會減小不會變大。
對于一個X,要么本身就是fib數,要么用比X大的最小fib數減掉一個數,要么用比X小的最大fib數來加上一個數。
這個故事告訴我們,求出所有fib數后,直接記憶化搜索就可以了。
上代碼:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
long long n,fib[90],f[10000000],x;
int ans(long long x)
{
int r;
if ((x<10000000)&&(f[x]!=0)) return f[x];
for (int i=1;i<=85;i++)
if (fib[i]>x)
{ r=i; break; }
if ((fib[r]==x)||(fib[r-1]==x)) { return 1; f[x]=1; }
if (x<10000000) {
f[x]=min(ans(fib[r-1])+ans(x-fib[r-1]),ans(fib[r])+ans(fib[r]-x));
return f[x];}
return min(ans(fib[r-1])+ans(x-fib[r-1]),ans(fib[r])+ans(fib[r]-x));
return f[x];
}
int main()
{
freopen("fib.in","r",stdin);
freopen("fib.out","w",stdout);
fib[1]=fib[2]=1; cin>>n;
for (int i=3;i<=85;i++) fib[i]=fib[i-1]+fib[i-2];
//for (int i=1;i<=85;i++) cout<<fib[i]<<' ';
for (int i=1;i<=n;i++) cin>>x,cout<<ans(x)<<endl;
//cout<<ans(5);
return 0;
}
總結
- 上一篇: Android MVP 架构一 View
- 下一篇: 没接到信用卡审核电话怎么办?可以尝试这么