zoukankan      html  css  js  c++  java
  • 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;
    }
    
    
    
  • 相关阅读:
    准备开发一门科学(工程)计算语言
    编译器二次开发定制服务?
    C#中的委托
    asp.net网页代码清理文件夹下面的数据
    类型“System.Web.UI.UpdatePanel”不具有名为“DropDownList”的公共属性,解决方法
    AutoPostBack 与UpdatePanel的局部刷新
    asp.net截取指定字符后面的字符串
    asp.net 各种格式的时间格式
    UpdatePane刷新和Ajax控件Timer的问题,刷新没有效果,解决方法
    ACCESS模糊查询
  • 原文地址:https://www.cnblogs.com/sz-wcc/p/13194339.html
Copyright © 2011-2022 走看看