题解 P3539 【[POI2012]ROZ-Fibonacci Representation】
给定正整数
k ,求用斐波那契数的和或差表示k 所需要的斐波那契数数量最小值。k \leq 4\times 10^7 时空限制:
\texttt{1s/125MB}
题解界面 LaTeX 渲染可能会有点问题,建议到博客中查看:题解 P3539 【[POI2012]ROZ-Fibonacci Representation】
这题的贪心做法是这样的:每次找到一个离
但是我在网上一直找不到比较好的证明,非常自闭QAQ。
首先有几个性质:
-
存在最优方案,不会选择重复的一项。
证明: 因为我们有
2F_i=F_{i+1}+F_{i-2} 。 -
存在最优方案,不会选择相邻的两项。
证明: 通过讨论可以知道
+F_i+F_{i+1}=+F_{i+2} +F_i-F_{i+1}=-F_{i-1} -F_i+F_{i+1}=+F_{i-1} -F_i-F_{i+1}=-F_{i+2} -
若当前
F_i \leq k \leq F_{i+1} ,那么存在最优方案,一定包含了F_i 或F_{i+1} 。证明: 反证法。假设不包含
F_i 和F_{i+1} 。那么根据不选相邻和重复的原则,我们可以证明其他部分的斐波那契数通过加减一定无法凑到[F_i,F_{i+1}] 内的数。具体地,我们有F_{i-1}+F_{i-3}+\cdots<F_i 成立,这是因为F_1+F_3+\cdots +F_{2n-1}=F_{2n}-1 和F_2+F_4+\cdots +F_{2n}=F_{2n+1}-1 (为方便设F_1=1,F_2=2 )。这样一来,
F_1\sim F_{i-1} 的数里选出来的和S<F_i 。同样我们如果用比F_{i+1} 大的数拿去减,也会遇到这种的情况:F_{i+2}-S>F_{i+1} ,并且因为不能选相邻的,F_{i+4}-F_{i+2}>F_{i+3} 也是没用的。因此我们就证明了,存在最优方案,一定包含了
F_i 或F_{i+1} 。
那么接下来,我们就得到了,若当前
接下来我们归纳证明,一定是选较近的那个斐波那契数:
- 显然对于满足
k < F_3 的k ,结论成立。 - 假设对于满足
k < F_i 的k ,结论是成立的,那么接下来考虑证明对于满足F_i\leq k<F_{i+1} 的k ,有结论成立。不妨假设k-F_i=a ,F_{i+1}-k=b ,不失一般性地,设a<b ,对于a>b 同理。 - 接下来证明令
k\leftarrow a 的策略不比k \leftarrow b 的策略劣。首先有a+b=F_{i+1}-F_{i}=F_{i-1} 。根据a<b 我们有b\in (\frac{F_{i-1}}2,F_{i-1}] ,并且因为F_{i-3}<\frac{F_{i-1}}{2}<F_{i-2}<F_{i-1} ,而\frac{F_{i-1}}2=\frac{F_{i-2}+F_{i-3}}2 ,因此离b 最近的斐波那契数一定是F_{i-2},F_{i-1} 之一。 - 因为
b \leq F_{i-1}<F_i 满足一定选离b 较近的斐波那契数,因此我们有b 的最优表示中一定有F_{i-2},F_{i-1} 之一。那么a=F_{i-1}-b ,所以a 可以由b 的表达转化过来,并且F_{i-1} 可以和b 的表示中的F_{i-2} 或是F_{i-1} 合并/抵消,因此a 均能得到一种不劣于b 的表达方式。
至此我们证明了贪心策略的正确性。
显然,
#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;
}