51Nod 1350 斐波那契表示

Problem

每一个正整数都可以表示为若干个斐波那契数的和,一个整数可能存在多种不同的表示方法,例如:14 = 13 + 1 = 8 + 5 + 1,其中13 + 1是最短的表示(只用了2个斐波那契数)。定义F(n) = n的最短表示中的数字个数,F(14) = 2,F(100) = 3(100 = 3 + 8 + 89),F(16) = 2(16 = 8 + 8 = 13 + 3)。定义G(n) = F(1) + F(2) + F(3) + ...... F(n),G(6) = 1 + 1 + 1 + 2 + 1 + 2 = 8。给出若干个数字n,求对应的G(n)。

Solution

以fib个为一组找规律,发现当前fib[i]个数是前fib[i-1]个数照搬,然后前前fib[i-2]个数搬过来再+1,于是预处理fib和fib前缀和,还有sum和sum前缀和,sum[i]代表一组数,有fib[i]个,他们的F之和,然后二分找到前面成组的数,不成组的按照规律,递归求解。

Code

#include<stdio.h>
#include<set>
#include<iostream>
#include<stack>
#include<cstring>
#include<cmath>
#include<vector>
#include<map>
#include<queue>
#include<algorithm>
typedef long long ll;
typedef long double ld;
typedef double db;
#define io_opt ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
const int mod=1e9+7;
inline int mo(ll a,int p){
    return a>=p?a%p:a;
}
inline int rd() {
    int x = 0, f = 1;
    char ch;
    while (ch < '0' || ch > '9') {
        if (ch == '-')f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return f * x;
}
inline ll gcd(ll x, ll y){
    return y==0?x:gcd(y,x%y);
}
inline ll speed(ll a,ll b){
    ll cur=a,anss=1;
    while(b){
        if(b&1) anss=anss*cur;
        cur=cur*cur;
        b>>=1;
    }
    return anss;
}
const int MAXN=1e5;
bool ipr[MAXN+20];
int cnt,pri[MAXN/5];
void prime(){//埃式筛法
    int N=sqrt(MAXN)+0.5,mul;
    memset(ipr,true,sizeof(ipr));
    ipr[1]=false;
    for(int i=2;i<=N;i++){
        if(ipr[i]==true){
            i==2?mul=1:mul=2;
            for(int j=i*i;j<=MAXN;j+=i*mul){
                ipr[j]=false;
            }
        }
    }
    for(int i=2;i<=MAXN;i++){
        if(ipr[i]==true){
            pri[++cnt]=i;
        }
    }
}
int T;
ll n;
ll fib[120]={1,1},sfib[120]={0,1};
ll sum[120]={0,1,3},ssum[120]={0,1,4};
ll dfs(ll layer,ll cur){
    if(layer<=0||cur<=0) return 0;
    if(cur==fib[layer]) return sum[layer];
    if(cur<=fib[layer-1]) return dfs(layer-1,cur);
    return sum[layer-1]+dfs(layer-2,cur-fib[layer-1])+cur-fib[layer-1];
}
int main(){
    //io_opt;
    for(int i=2;i<=91;i++){
        fib[i]=fib[i-1]+fib[i-2];
        sfib[i]=sfib[i-1]+fib[i];
    }
    for(int i=3;i<=91;i++){
        sum[i]=sum[i-1]+sum[i-2]+fib[i-2];
        ssum[i]=ssum[i-1]+sum[i];
        //81>0
    }
    scanf("%d",&T);
    while(T--){
        scanf("%lld",&n);
        n--;
        ll ans=1,cur=n;
        ll p=lower_bound(sfib+1,sfib+1+81,cur)-sfib-1;
        //cout<<"!"<<p<<endl;
        cur-=sfib[p];
        ans+=ssum[p];
        p++;
        ans+=dfs(p,cur);
        printf("%lld
",ans);
    }
    return 0;
}


原文地址:https://www.cnblogs.com/sz-wcc/p/13194339.html