zoukankan      html  css  js  c++  java
  • 51Nod 1350 斐波那契表示

    51Nod 1350 斐波那契表示


    题意:

    每一个正整数都可以表示为若干个斐波那契数的和,一个整数可能存在多种不同的表示方法,例如: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)。

    做法

    首先可以知道 fib(i-1)到fib(i)-1之间的数,一定是fib(i-1)与之前的数组合出的,那么考虑可不可以计算G(fib(i))
    G(fib(i)) = G(fib(i-1)) + (F(fib(i-1)+1)+...+F(fib(i)))

    除掉最后一项为1,其余的 F(fib(i-1)+1),...,F(fib(i)-1) 一共fib(i-2)-1个数
    他们的组合一定包含fib(i-1),因此贪心的考虑可以知道:
    F(fib(i-1)+1) = 1 + F(1)
    F(fib(i-1)+2) = 1 + F(2)
    F(fib(i-1)+3) = 1 + F(3)
    ...
    因此,可以得到
    G(fib(i))
    = G(fib(i-1)) + (1 + F(1) + 1 + F(2) + ... + 1+F(fib(i-2)-1) + 1)
    = G(fib(i-1)) + (F(1) + F(2) + ... + F(fib(i-2)-1)) + fib(i-2)
    = G(fib(i-1)) + G(fib(i-2)-1) + fib(i-2)
    现在考虑求任意G(n),通过类似的思想,可推出:
    G(n) = G(fib(m)) + G(n-fib(m)) + n - fib(m)
    2个式子n下降的速度与fib数列同级别,因此复杂度有保证。
    直接用map记忆化tle了,使用unordered_map通过

    #include <bits/stdc++.h>
    #define rep(i,a,b) for(int i=(a);i<=(b);++i)
    #define per(i,a,b) for(int i=(a);i>=(b);--i)
    #define pb push_back
    typedef long long ll;
    using namespace std;
    const int N = 100100;
    
    int sz;
    ll fib[N], n;
    unordered_map<ll,ll> isFib, ans;
    ll G(ll n) {
        if(n == 1) {return 1;}
        if(n == 2) {return 2;}
        if(n == 3) {return 3;}
        if(ans.find(n)!=ans.end())return ans[n];
        
        if(isFib.find(n) != isFib.end()) {
            int p = isFib[n];
            return ans[n] = fib[p-2] + G(fib[p-2]-1) + G(fib[p-1]);
        }
        else {
            per(i,sz,1)if(fib[i]<=n){
                return ans[n] = G(fib[i])+G(n-fib[i])+n-fib[i];
            }
        }
    }
    int main () {
        ios::sync_with_stdio(false); cin.tie(false);
        fib[0] = fib[1] = 1;
        isFib[fib[1]] = 1;
        rep(i, 2, 100) {
            fib[i] = fib[i-1] + fib[i-2];
            isFib[fib[i]] = i;
            if(fib[i] >= 1e17) {
                sz = i;break;
            }
        }
        int _; cin >> _; while(_--) {
            cin >> n;
            cout << G(n) << "
    ";
        }
        return 0;
    }
    
  • 相关阅读:
    Maximum Depth of Binary Tree
    Single Number
    Merge Two Sorted Lists
    Remove Nth Node From End of List
    Remove Element
    Remove Duplicates from Sorted List
    Add Two Numbers
    编译视频直播点播平台EasyDSS数据排序使用Go 语言 slice 类型排序的实现介绍
    RTMP协议视频直播点播平台EasyDSS在Linux系统中以服务启动报错can’t evaluate field RootPath in type*struct排查
    【解决方案】5G时代RTMP推流服务器/互联网直播点播平台EasyDSS实现360°全景摄像机VR直播
  • 原文地址:https://www.cnblogs.com/RRRR-wys/p/13662452.html
Copyright © 2011-2022 走看看