题解 P4133 【[BJOI2012]最多的方案】

· · 题解

分析

具体的可以参考:Zeckendorf's theorem

简单证明:

可以考虑归纳,显然对于 n \leq 3 这个结论是成立的。

f_k 表示斐波那契数列的第 k 项,假设对于满足 n < f_{k} 的自然数都能被不相同的斐波那契数表示,那么对于 n=f_k 显然可以直接用 f_k 表示。

对于满足 f_k<n<f_{k+1} 的整数 n,因为 n<f_{k+1}\leq 2f_{k},因此 n-f_k<f_k,所以 n-f_k 的斐波那契数表示中肯定不包含 f_k,我们可以考虑用 n-f_k 的斐波那契数表示加上 f_k,从而得到 n 的斐波那契数表示。

g[i][1]=g[i-1][1]+g[i-1][0] g[i][0]=g[i-1][1]*((pos[i]-pos[i-1]-1)\ div\ 2)+g[i-1][0]*((pos[i]-pos[i-1])\ div\ 2)

代码:

#include <cmath>
#include <cstdio>
#include <cctype>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

typedef long long ll; 

const int MaxN = 110; 

ll n, f[MaxN]; 
int m, cnt, pos[MaxN]; 
int g[MaxN][2]; 

int main()
{
    std::cin >> n; 
    f[1] = 1, f[2] = 2; 
    for (m = 3; f[m - 1] <= n; ++m)
        f[m] = f[m - 1] + f[m - 2]; 
    --m; 
    for (int i = m; i >= 1; --i)
        if (n >= f[i])
        {
            n -= f[i]; 
            pos[++cnt] = i; 
        }
    std::sort(pos + 1, pos + cnt + 1); 
    g[1][1] = 1, g[1][0] = pos[1] - 1 >> 1; 
    for (int i = 2; i <= cnt; ++i)
    {
        g[i][1] = g[i - 1][0] + g[i - 1][1]; 
        g[i][0] = g[i - 1][1] * (pos[i] - pos[i - 1] - 1 >> 1) + g[i - 1][0] * (pos[i] - pos[i - 1] >> 1);  
    }

    printf("%d\n", g[cnt][0] + g[cnt][1]);  

    return 0; 
}