51NOD 1350 斐波那契表示 规律+递归

来源:互联网 发布:如何退出淘宝客 编辑:程序博客网 时间:2024/05/21 03:26
题意:定义f(n)为:n最少需要用多少个fib数来表示. f(16)=2(16 =13+3 = 8+8)
定义g(n)=f(1)+f(2)+...f(n) Q次询问 每次给出一个n 求出g(n) n<=1e17.


先求f(n):每次用n减去当前最大的fib.
n很大 求g(n)时尝试打表:第i段 fib[i]个,则第i段的和w[i]=w[i-1]+(w[i-2]+f(i-2)).

n分解成若干段 最后一段只有x个 不满fib(i)时,可以将第i个区间不断分解 递归求解即可.

#include <bits/stdc++.h>using namespace std;typedef long long ll;const int N=2e3+5;ll f[N],w[N],m=0;void init(){f[1]=f[2]=1;w[1]=w[2]=1;for(int i=3;;i++){f[i]=f[i-1]+f[i-2];w[i]=w[i-1]+w[i-2]+f[i-2];if(f[i]>1e17)break;}}ll calc(ll i,ll x){if(x==f[i])return w[i];if(x<=f[i-1])return calc(i-1,x);//  f[i-1]<x<f[i]return w[i-1]+calc(i-2,x-f[i-1])+x-f[i-1];}int main(){init();int T;cin>>T;while(T--){ll n;scanf("%I64d",&n);ll id=0,sum=0,ans=0;while(sum+f[id+1]<n)sum+=f[++id];for(int i=1;i<=id;i++)ans+=w[i];ans+=calc(id+1,n-sum);printf("%I64d\n",ans);}return 0;}


原创粉丝点击