题解 P3539 【[POI2012]ROZ-Fibonacci Representation】

· · 题解

给定正整数 k,求用斐波那契数的和或差表示 k 所需要的斐波那契数数量最小值。

k \leq 4\times 10^7

时空限制:\texttt{1s/125MB}

题解界面 LaTeX 渲染可能会有点问题,建议到博客中查看:题解 P3539 【[POI2012]ROZ-Fibonacci Representation】

这题的贪心做法是这样的:每次找到一个离 k 最近的斐波那契数 F_i,令 k\leftarrow|k-F_i|,重复若干次直到 k=0。(即每次令 k \leftarrow \min|k-F_i|

但是我在网上一直找不到比较好的证明,非常自闭QAQ。

首先有几个性质:

那么接下来,我们就得到了,若当前 F_{i}\leq k \leq F_{i+1},我们一定要从 F_i,F_{i+1} 中选一个。

接下来我们归纳证明,一定是选较近的那个斐波那契数:

至此我们证明了贪心策略的正确性。

显然,k 每次至少减少一半,所以答案是 \mathcal O(\log k) 级别的,这也是时间复杂度的级别。

#include <bits/stdc++.h>

typedef long long s64; 

const s64 lim = 4e17; 

int main()
{
    static s64 f[10001];

    int m = 2; 
    f[1] = 1, f[2] = 2; 
    while (f[m] <= lim)
    {
        ++m; 
        f[m] = f[m - 2] + f[m - 1]; 
    }

    int orzczk; 
    std::cin >> orzczk; 
    while (orzczk--)
    {
        s64 n; 
        int res = 0; 
        std::cin >> n; 
        while (n)
        {
            ++res; 
            int suf = std::upper_bound(f + 1, f + m + 1, n) - f; 
            n = std::min(f[suf] - n, n - f[suf - 1]); 
        }
        std::cout << res << '\n'; 
    }
    return 0; 
}